From 03c549e0392f92c02536d3f86d5e1d8dfa3435ac Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 1 Sep 2021 11:08:40 +0200 Subject: BASELINE: Update Chromium to 91.0.4472.160 Change-Id: I0def1f08a2412aeed79a9ab95dd50eb5c3f65f31 Reviewed-by: Allan Sandfeld Jensen --- .../ca_transaction_observer.h | 2 + chromium/ui/accessibility/BUILD.gn | 6 +- chromium/ui/accessibility/PRESUBMIT.py | 4 + .../ui/accessibility/accessibility_features.cc | 15 + chromium/ui/accessibility/accessibility_features.h | 14 + .../ui/accessibility/accessibility_switches.cc | 22 +- chromium/ui/accessibility/accessibility_switches.h | 9 +- chromium/ui/accessibility/ax_action_handler.cc | 4 +- chromium/ui/accessibility/ax_action_handler.h | 3 +- .../ui/accessibility/ax_action_handler_base.cc | 8 +- chromium/ui/accessibility/ax_action_handler_base.h | 2 +- .../ui/accessibility/ax_action_handler_registry.cc | 111 ++ .../ui/accessibility/ax_action_handler_registry.h | 117 ++ .../ui/accessibility/ax_assistant_structure.cc | 33 +- chromium/ui/accessibility/ax_assistant_structure.h | 10 +- chromium/ui/accessibility/ax_common.h | 23 + chromium/ui/accessibility/ax_enum_util.cc | 6 +- chromium/ui/accessibility/ax_enum_util_unittest.cc | 13 +- chromium/ui/accessibility/ax_enums.mojom | 3 +- chromium/ui/accessibility/ax_event_bundle_sink.h | 41 - chromium/ui/accessibility/ax_event_generator.cc | 128 +- chromium/ui/accessibility/ax_event_generator.h | 73 +- chromium/ui/accessibility/ax_language_detection.cc | 5 +- chromium/ui/accessibility/ax_node.cc | 196 ++- chromium/ui/accessibility/ax_node.h | 41 +- chromium/ui/accessibility/ax_node_data.cc | 50 +- chromium/ui/accessibility/ax_node_data.h | 28 +- .../ui/accessibility/ax_node_position_unittest.cc | 64 +- chromium/ui/accessibility/ax_position.h | 330 ++-- chromium/ui/accessibility/ax_range.h | 48 +- chromium/ui/accessibility/ax_range_unittest.cc | 245 ++- chromium/ui/accessibility/ax_role_properties.cc | 12 +- chromium/ui/accessibility/ax_table_info.cc | 5 +- chromium/ui/accessibility/ax_table_info.h | 5 + .../ui/accessibility/ax_table_info_unittest.cc | 15 +- chromium/ui/accessibility/ax_text_utils.cc | 10 +- chromium/ui/accessibility/ax_text_utils.h | 16 +- .../ui/accessibility/ax_text_utils_unittest.cc | 32 +- chromium/ui/accessibility/ax_tree.cc | 26 +- chromium/ui/accessibility/ax_tree.h | 11 - chromium/ui/accessibility/ax_tree_combiner.h | 2 +- .../ui/accessibility/ax_tree_combiner_unittest.cc | 6 +- chromium/ui/accessibility/ax_tree_data.h | 3 +- chromium/ui/accessibility/ax_tree_id.cc | 5 +- chromium/ui/accessibility/ax_tree_id_registry.cc | 87 - chromium/ui/accessibility/ax_tree_id_registry.h | 87 - chromium/ui/accessibility/ax_tree_id_unittest.cc | 24 + chromium/ui/accessibility/ax_tree_unittest.cc | 12 +- .../accessibility_extensions_strings_gu.xtb | 4 +- .../accessibility_extensions_strings_ne.xtb | 4 +- .../mojom/ax_assistant_structure_mojom_traits.h | 2 +- chromium/ui/accessibility/platform/BUILD.gn | 6 +- .../accessibility/platform/ax_android_constants.cc | 2 +- .../accessibility/platform/ax_android_constants.h | 5 +- .../ui/accessibility/platform/ax_platform_node.h | 2 +- .../platform/ax_platform_node_auralinux.cc | 22 +- .../platform/ax_platform_node_auralinux.h | 4 - .../platform/ax_platform_node_base.cc | 53 +- .../accessibility/platform/ax_platform_node_base.h | 30 +- .../platform/ax_platform_node_base_unittest.cc | 33 +- .../platform/ax_platform_node_delegate.h | 18 +- .../platform/ax_platform_node_delegate_base.cc | 40 +- .../platform/ax_platform_node_delegate_base.h | 18 +- .../accessibility/platform/ax_platform_node_mac.h | 2 +- .../accessibility/platform/ax_platform_node_mac.mm | 3 +- ...platform_node_textchildprovider_win_unittest.cc | 5 +- .../platform/ax_platform_node_textprovider_win.cc | 13 + .../platform/ax_platform_node_textprovider_win.h | 6 +- .../ax_platform_node_textprovider_win_unittest.cc | 109 +- .../ax_platform_node_textrangeprovider_win.cc | 9 +- .../ax_platform_node_textrangeprovider_win.h | 2 +- ...platform_node_textrangeprovider_win_unittest.cc | 42 +- .../accessibility/platform/ax_platform_node_win.cc | 69 +- .../accessibility/platform/ax_platform_node_win.h | 2 +- .../platform/ax_platform_node_win_unittest.cc | 148 +- .../platform/ax_platform_node_win_unittest.h | 2 +- .../accessibility/platform/ax_system_caret_win.cc | 2 +- .../platform/inspect/ax_inspect_scenario.cc | 123 ++ .../platform/inspect/ax_inspect_scenario.h | 131 ++ .../platform/inspect/ax_inspect_utils_win.cc | 112 +- .../platform/inspect/ax_inspect_utils_win.h | 72 + .../platform/inspect/ax_tree_formatter.h | 7 + .../platform/inspect/ax_tree_formatter_base.cc | 9 + .../platform/inspect/ax_tree_formatter_base.h | 5 + .../accessibility/platform/test_ax_node_wrapper.cc | 102 +- .../accessibility/platform/test_ax_node_wrapper.h | 16 +- chromium/ui/accessibility/test_ax_node_helper.cc | 25 +- chromium/ui/accessibility/test_ax_node_helper.h | 5 + chromium/ui/android/BUILD.gn | 9 +- chromium/ui/android/DEPS | 1 + .../ui/android/delegated_frame_host_android.cc | 13 +- chromium/ui/android/delegated_frame_host_android.h | 3 + chromium/ui/android/event_forwarder.cc | 2 +- .../org/chromium/ui/widget/LoadingViewTest.java | 133 ++ chromium/ui/aura/BUILD.gn | 6 + chromium/ui/aura/client/aura_constants.cc | 4 +- chromium/ui/aura/client/aura_constants.h | 3 +- chromium/ui/aura/client/cursor_client.h | 3 +- .../ui/aura/client/drag_drop_client_observer.h | 16 +- chromium/ui/aura/env.cc | 9 - chromium/ui/aura/env_observer.h | 5 - .../ui/aura/native_window_occlusion_tracker_win.cc | 29 +- .../ui/aura/native_window_occlusion_tracker_win.h | 3 +- ...indow_occlusion_tracker_win_interactive_test.cc | 32 + chromium/ui/aura/screen_ozone.h | 3 + chromium/ui/aura/test/ui_controls_ozone.cc | 10 + chromium/ui/aura/window.cc | 6 +- chromium/ui/aura/window.h | 5 +- chromium/ui/aura/window_observer.h | 3 +- chromium/ui/aura/window_tree_host_platform.cc | 4 +- chromium/ui/aura/window_tree_host_platform.h | 2 +- chromium/ui/aura_extra/image_window_delegate.cc | 8 +- chromium/ui/aura_extra/image_window_delegate.h | 17 +- chromium/ui/base/BUILD.gn | 35 +- chromium/ui/base/OWNERS | 2 + chromium/ui/base/accelerators/accelerator.cc | 152 +- chromium/ui/base/accelerators/accelerator.h | 24 +- .../ui/base/accelerators/accelerator_history.cc | 91 -- .../ui/base/accelerators/accelerator_history.h | 60 - .../accelerators/accelerator_history_unittest.cc | 75 - .../ui/base/accelerators/accelerator_manager.cc | 175 +- .../ui/base/accelerators/accelerator_manager.h | 61 +- .../ui/base/accelerators/accelerator_unittest.cc | 27 +- .../accelerators/menu_label_accelerator_util.cc | 16 +- .../accelerators/menu_label_accelerator_util.h | 5 +- .../menu_label_accelerator_util_unittest.cc | 13 +- chromium/ui/base/clipboard/BUILD.gn | 67 +- chromium/ui/base/clipboard/OWNERS | 5 +- chromium/ui/base/clipboard/clipboard.cc | 98 +- chromium/ui/base/clipboard/clipboard.h | 99 +- chromium/ui/base/clipboard/clipboard_android.cc | 92 +- chromium/ui/base/clipboard/clipboard_android.h | 17 +- .../clipboard/clipboard_android_test_support.cc | 2 +- .../ui/base/clipboard/clipboard_factory_ozone.cc | 56 + chromium/ui/base/clipboard/clipboard_format_type.h | 2 +- chromium/ui/base/clipboard/clipboard_linux.cc | 33 - chromium/ui/base/clipboard/clipboard_mac.h | 16 +- chromium/ui/base/clipboard/clipboard_mac.mm | 100 +- chromium/ui/base/clipboard/clipboard_non_backed.cc | 40 +- chromium/ui/base/clipboard/clipboard_non_backed.h | 16 +- .../clipboard/clipboard_non_backed_unittest.cc | 8 +- chromium/ui/base/clipboard/clipboard_ozone.cc | 61 +- chromium/ui/base/clipboard/clipboard_ozone.h | 16 +- .../ui/base/clipboard/clipboard_test_template.h | 109 +- chromium/ui/base/clipboard/clipboard_util_win.cc | 24 +- chromium/ui/base/clipboard/clipboard_util_win.h | 9 +- chromium/ui/base/clipboard/clipboard_win.cc | 46 +- chromium/ui/base/clipboard/clipboard_win.h | 16 +- chromium/ui/base/clipboard/clipboard_x11.cc | 653 ++------ chromium/ui/base/clipboard/clipboard_x11.h | 33 +- chromium/ui/base/clipboard/custom_data_helper.cc | 24 +- chromium/ui/base/clipboard/custom_data_helper.h | 14 +- .../base/clipboard/custom_data_helper_unittest.cc | 93 +- .../ui/base/clipboard/scoped_clipboard_writer.cc | 12 +- .../ui/base/clipboard/scoped_clipboard_writer.h | 13 +- chromium/ui/base/cocoa/command_dispatcher.h | 10 +- chromium/ui/base/cocoa/command_dispatcher.mm | 2 +- chromium/ui/base/cocoa/find_pasteboard.h | 5 +- chromium/ui/base/cocoa/find_pasteboard.mm | 2 +- chromium/ui/base/cocoa/menu_controller.h | 3 +- chromium/ui/base/cocoa/menu_controller_unittest.mm | 96 +- .../ui/base/cocoa/text_services_context_menu.cc | 2 +- .../ui/base/cocoa/text_services_context_menu.h | 7 +- chromium/ui/base/cursor/cursor_factory.cc | 15 +- chromium/ui/base/cursor/cursor_factory.h | 20 +- chromium/ui/base/cursor/cursor_loader.cc | 30 +- chromium/ui/base/cursor/cursor_loader_unittest.cc | 9 +- chromium/ui/base/cursor/cursors_aura.cc | 39 +- chromium/ui/base/cursor/mojom/cursor_type.mojom | 4 + .../cursor/ozone/bitmap_cursor_factory_ozone.cc | 56 +- .../cursor/ozone/bitmap_cursor_factory_ozone.h | 19 +- .../ozone/bitmap_cursor_factory_ozone_unittest.cc | 36 +- chromium/ui/base/cursor/win/win_cursor_factory.cc | 10 +- chromium/ui/base/cursor/win/win_cursor_factory.h | 3 +- .../data_transfer_policy_controller.h | 16 + chromium/ui/base/dragdrop/BUILD.gn | 23 + chromium/ui/base/dragdrop/cocoa_dnd_util.h | 4 +- chromium/ui/base/dragdrop/cocoa_dnd_util.mm | 2 +- chromium/ui/base/dragdrop/drag_drop_types.h | 2 +- chromium/ui/base/dragdrop/drag_drop_types_mac.mm | 2 +- chromium/ui/base/dragdrop/mojom/BUILD.gn | 4 +- chromium/ui/base/dragdrop/os_exchange_data.cc | 12 +- chromium/ui/base/dragdrop/os_exchange_data.h | 12 +- .../ui/base/dragdrop/os_exchange_data_provider.h | 17 +- .../base/dragdrop/os_exchange_data_provider_mac.h | 13 +- .../base/dragdrop/os_exchange_data_provider_mac.mm | 32 +- .../os_exchange_data_provider_non_backed.cc | 36 +- .../os_exchange_data_provider_non_backed.h | 27 +- ...s_exchange_data_provider_non_backed_unittest.cc | 22 +- .../base/dragdrop/os_exchange_data_provider_win.cc | 20 +- .../base/dragdrop/os_exchange_data_provider_win.h | 12 +- .../os_exchange_data_provider_x11_unittest.cc | 21 +- .../ui/base/dragdrop/os_exchange_data_unittest.cc | 32 +- .../base/dragdrop/os_exchange_data_win_unittest.cc | 30 +- chromium/ui/base/emoji/emoji_panel_helper.h | 7 + .../ui/base/emoji/emoji_panel_helper_chromeos.cc | 14 + chromium/ui/base/glib/OWNERS | 1 + chromium/ui/base/glib/glib_cast.h | 18 + chromium/ui/base/glib/scoped_gobject.h | 66 +- chromium/ui/base/hit_test_x11.h | 4 +- chromium/ui/base/idle/BUILD.gn | 7 +- chromium/ui/base/idle/DEPS | 1 + chromium/ui/base/idle/idle_lacros.cc | 29 + chromium/ui/base/ime/candidate_window.h | 10 +- chromium/ui/base/ime/candidate_window_unittest.cc | 6 +- chromium/ui/base/ime/character_composer.cc | 4 +- chromium/ui/base/ime/character_composer.h | 8 +- .../ui/base/ime/character_composer_unittest.cc | 142 +- chromium/ui/base/ime/composition_text.cc | 13 +- chromium/ui/base/ime/composition_text.h | 21 +- chromium/ui/base/ime/composition_text_unittest.cc | 2 +- chromium/ui/base/ime/dummy_input_method.cc | 13 +- chromium/ui/base/ime/dummy_input_method.h | 4 +- chromium/ui/base/ime/dummy_text_input_client.cc | 6 +- chromium/ui/base/ime/dummy_text_input_client.h | 14 +- chromium/ui/base/ime/fake_text_input_client.cc | 22 +- chromium/ui/base/ime/fake_text_input_client.h | 13 +- chromium/ui/base/ime/fuchsia/BUILD.gn | 4 + chromium/ui/base/ime/fuchsia/OWNERS | 1 + .../ui/base/ime/fuchsia/input_method_fuchsia.cc | 61 +- .../ui/base/ime/fuchsia/input_method_fuchsia.h | 48 +- chromium/ui/base/ime/fuchsia/keyboard_client.cc | 167 ++ chromium/ui/base/ime/fuchsia/keyboard_client.h | 69 + .../fuchsia/virtual_keyboard_controller_fuchsia.cc | 91 +- .../fuchsia/virtual_keyboard_controller_fuchsia.h | 26 +- chromium/ui/base/ime/infolist_entry.cc | 4 +- chromium/ui/base/ime/infolist_entry.h | 9 +- chromium/ui/base/ime/input_method.h | 22 +- chromium/ui/base/ime/input_method_base.cc | 13 +- chromium/ui/base/ime/input_method_base.h | 5 +- chromium/ui/base/ime/input_method_base_unittest.cc | 2 - .../base/ime/linux/composition_text_util_pango.cc | 3 +- .../ui/base/ime/linux/fake_input_method_context.cc | 5 +- .../ui/base/ime/linux/fake_input_method_context.h | 2 +- .../ui/base/ime/linux/input_method_auralinux.cc | 370 +++-- .../ui/base/ime/linux/input_method_auralinux.h | 41 +- .../ime/linux/input_method_auralinux_unittest.cc | 97 +- .../ui/base/ime/linux/linux_input_method_context.h | 7 +- chromium/ui/base/ime/mock_input_method.cc | 13 +- chromium/ui/base/ime/mock_input_method.h | 4 +- chromium/ui/base/ime/text_input_client.h | 10 +- chromium/ui/base/ime/utf_offset.cc | 3 +- chromium/ui/base/ime/utf_offset_unittest.cc | 10 +- chromium/ui/base/ime/win/imm32_manager.cc | 23 +- chromium/ui/base/ime/win/imm32_manager.h | 7 +- chromium/ui/base/ime/win/input_method_win_base.cc | 46 +- chromium/ui/base/ime/win/input_method_win_base.h | 7 + .../on_screen_keyboard_display_manager_unittest.cc | 3 +- chromium/ui/base/ime/win/tsf_text_store.cc | 14 +- chromium/ui/base/ime/win/tsf_text_store.h | 12 +- .../ui/base/ime/win/tsf_text_store_unittest.cc | 254 +-- chromium/ui/base/l10n/formatter.cc | 54 +- chromium/ui/base/l10n/l10n_util.cc | 153 +- chromium/ui/base/l10n/l10n_util.h | 100 +- chromium/ui/base/l10n/l10n_util_android.cc | 2 +- chromium/ui/base/l10n/l10n_util_android.h | 3 +- chromium/ui/base/l10n/l10n_util_collator.h | 16 +- chromium/ui/base/l10n/l10n_util_mac.h | 59 +- chromium/ui/base/l10n/l10n_util_mac.mm | 66 +- chromium/ui/base/l10n/l10n_util_mac_unittest.mm | 4 +- chromium/ui/base/l10n/l10n_util_unittest.cc | 70 +- chromium/ui/base/l10n/time_format.cc | 21 +- chromium/ui/base/l10n/time_format.h | 13 +- chromium/ui/base/l10n/time_format_unittest.cc | 560 ++++--- chromium/ui/base/linux/OWNERS | 1 + chromium/ui/base/linux/linux_desktop.cc | 45 + chromium/ui/base/linux/linux_desktop.h | 21 + chromium/ui/base/models/button_menu_item_model.cc | 12 +- chromium/ui/base/models/button_menu_item_model.h | 10 +- chromium/ui/base/models/combobox_model.cc | 6 +- chromium/ui/base/models/combobox_model.h | 9 +- chromium/ui/base/models/dialog_model.cc | 12 +- chromium/ui/base/models/dialog_model.h | 30 +- chromium/ui/base/models/dialog_model_field.cc | 14 +- chromium/ui/base/models/dialog_model_field.h | 51 +- chromium/ui/base/models/dialog_model_unittest.cc | 8 +- chromium/ui/base/models/menu_model.cc | 8 +- chromium/ui/base/models/menu_model.h | 9 +- chromium/ui/base/models/simple_combobox_model.cc | 4 +- chromium/ui/base/models/simple_combobox_model.h | 6 +- chromium/ui/base/models/simple_menu_model.cc | 44 +- chromium/ui/base/models/simple_menu_model.h | 41 +- .../ui/base/models/simple_menu_model_unittest.cc | 55 +- chromium/ui/base/models/table_model.cc | 8 +- chromium/ui/base/models/table_model.h | 8 +- chromium/ui/base/models/tree_model.cc | 3 +- chromium/ui/base/models/tree_model.h | 6 +- chromium/ui/base/models/tree_node_model.h | 21 +- .../ui/base/models/tree_node_model_unittest.cc | 7 +- chromium/ui/base/prediction/linear_resampling.cc | 2 +- .../prediction_metrics_handler_unittest.cc | 4 +- .../base/resource/mock_resource_bundle_delegate.h | 2 +- chromium/ui/base/resource/resource_bundle.cc | 28 +- chromium/ui/base/resource/resource_bundle.h | 13 +- .../ui/base/resource/resource_bundle_unittest.cc | 18 +- chromium/ui/base/text/bytes_formatting.cc | 14 +- chromium/ui/base/text/bytes_formatting.h | 11 +- chromium/ui/base/ui_base_features.cc | 57 +- chromium/ui/base/ui_base_features.h | 14 + chromium/ui/base/webui/jstemplate_builder.cc | 3 +- chromium/ui/base/win/accessibility_misc_utils.cc | 2 +- chromium/ui/base/win/accessibility_misc_utils.h | 9 +- chromium/ui/base/win/message_box_win.cc | 7 +- chromium/ui/base/win/shell.h | 3 +- chromium/ui/base/window_open_disposition.h | 3 - chromium/ui/base/x/BUILD.gn | 43 +- chromium/ui/base/x/selection_requestor.cc | 15 +- chromium/ui/base/x/selection_requestor.h | 36 +- chromium/ui/base/x/selection_requestor_unittest.cc | 8 +- chromium/ui/base/x/selection_utils.cc | 33 +- chromium/ui/base/x/selection_utils.h | 13 +- chromium/ui/base/x/x11_clipboard_helper.cc | 413 +++++ chromium/ui/base/x/x11_clipboard_helper.h | 136 ++ chromium/ui/base/x/x11_cursor_factory.cc | 37 +- chromium/ui/base/x/x11_cursor_factory.h | 14 +- chromium/ui/base/x/x11_cursor_factory_unittest.cc | 1 + chromium/ui/base/x/x11_cursor_loader.cc | 13 +- chromium/ui/base/x/x11_cursor_loader.h | 3 +- chromium/ui/base/x/x11_cursor_loader_unittest.cc | 6 +- .../ui/base/x/x11_desktop_window_move_client.cc | 11 +- .../ui/base/x/x11_desktop_window_move_client.h | 20 +- chromium/ui/base/x/x11_drag_drop_client.cc | 1 + chromium/ui/base/x/x11_global_shortcut_listener.cc | 148 ++ chromium/ui/base/x/x11_global_shortcut_listener.h | 81 + chromium/ui/base/x/x11_menu_registrar.h | 3 +- .../ui/base/x/x11_os_exchange_data_provider.cc | 41 +- chromium/ui/base/x/x11_os_exchange_data_provider.h | 15 +- chromium/ui/base/x/x11_user_input_monitor.cc | 2 +- chromium/ui/base/x/x11_util.cc | 71 +- chromium/ui/base/x/x11_util.h | 13 +- chromium/ui/base/x/x11_window.cc | 1576 ------------------ chromium/ui/base/x/x11_window.h | 405 ----- .../x/x11_xrandr_interval_only_vsync_provider.cc | 42 + .../x/x11_xrandr_interval_only_vsync_provider.h | 34 + chromium/ui/chromeos/strings/BUILD.gn | 2 +- chromium/ui/color/BUILD.gn | 20 +- chromium/ui/color/OWNERS | 1 + chromium/ui/color/color_id.h | 99 +- chromium/ui/color/color_mixer.cc | 45 +- chromium/ui/color/color_mixer.h | 12 +- chromium/ui/color/color_mixer_unittest.cc | 27 +- chromium/ui/color/color_mixers.h | 21 +- chromium/ui/color/color_provider.cc | 58 +- chromium/ui/color/color_provider.h | 21 +- chromium/ui/color/color_provider_manager.cc | 75 +- chromium/ui/color/color_provider_manager.h | 30 +- .../ui/color/color_provider_manager_unittest.cc | 15 +- chromium/ui/color/color_provider_unittest.cc | 39 + chromium/ui/color/color_provider_utils.cc | 208 +++ chromium/ui/color/color_provider_utils.h | 44 + chromium/ui/color/color_recipe.cc | 9 +- chromium/ui/color/color_transform.cc | 140 +- chromium/ui/color/color_transform.h | 6 + chromium/ui/color/core_default_color_mixer.cc | 64 +- chromium/ui/color/cros/native_color_mixers.cc | 10 +- chromium/ui/color/fuchsia/native_color_mixers.cc | 10 +- chromium/ui/color/ios/native_color_mixers.mm | 25 + chromium/ui/color/linux/native_color_mixers.cc | 10 +- chromium/ui/color/mac/native_color_mixers.mm | 66 +- chromium/ui/color/mac/native_color_transform.mm | 25 + .../ui/color/mac/scoped_current_nsappearance.h | 2 +- .../ui/color/mac/scoped_current_nsappearance.mm | 16 +- chromium/ui/color/mac/system_color_utils.h | 30 + chromium/ui/color/mac/system_color_utils.mm | 38 + chromium/ui/color/ui_color_mixer.cc | 140 +- chromium/ui/color/win/native_color_mixers.cc | 158 +- chromium/ui/compositor/BUILD.gn | 9 + chromium/ui/compositor/OWNERS | 1 - chromium/ui/compositor/compositor.cc | 11 +- chromium/ui/compositor/layer_unittest.cc | 9 +- .../compositor/test/test_compositor_host_ozone.cc | 2 +- .../total_animation_throughput_reporter.cc | 3 + ...total_animation_throughput_reporter_unittest.cc | 31 + chromium/ui/display/manager/display_manager.h | 1 + .../ui/display/manager/touch_device_manager.cc | 40 +- chromium/ui/events/BUILD.gn | 2 +- chromium/ui/events/android/drag_event_android.cc | 2 +- chromium/ui/events/android/drag_event_android.h | 8 +- chromium/ui/events/base_event_utils.cc | 10 +- chromium/ui/events/base_event_utils.h | 7 + chromium/ui/events/blink/blink_features.cc | 3 + chromium/ui/events/blink/blink_features.h | 5 + chromium/ui/events/blink/fling_booster.cc | 8 + chromium/ui/events/cocoa/cocoa_event_utils.mm | 26 +- chromium/ui/events/devices/device_data_manager.cc | 9 + chromium/ui/events/devices/device_data_manager.h | 5 + .../ui/events/devices/input_device_observer_win.cc | 2 +- chromium/ui/events/event.cc | 17 +- chromium/ui/events/event.h | 11 +- chromium/ui/events/event_unittest.cc | 231 +++ chromium/ui/events/event_utils.cc | 181 +++ chromium/ui/events/event_utils.h | 41 +- chromium/ui/events/fuchsia/OWNERS | 1 + .../ui/events/fuchsia/input_event_dispatcher.cc | 71 +- .../ui/events/fuchsia/input_event_dispatcher.h | 10 +- .../fuchsia/input_event_dispatcher_delegate.h | 22 - .../fuchsia/input_event_dispatcher_unittest.cc | 83 +- chromium/ui/events/fuchsia/input_event_sink.h | 22 + .../events/gesture_detection/gesture_provider.cc | 7 +- .../gesture_detection/gesture_provider_unittest.cc | 162 ++ .../gesture_touch_uma_histogram.cc | 71 +- .../gesture_touch_uma_histogram.h | 13 +- chromium/ui/events/keycodes/dom_us_layout_data.h | 2 +- .../ui/events/keycodes/keyboard_code_conversion.cc | 4 +- .../ui/events/keycodes/keyboard_code_conversion.h | 7 +- .../keycodes/keyboard_code_conversion_mac.mm | 2 + .../events/keycodes/keyboard_code_conversion_x.cc | 2 +- .../events/keycodes/keyboard_code_conversion_x.h | 3 +- .../keycodes/keyboard_code_conversion_xkb.cc | 2 +- .../events/keycodes/keyboard_code_conversion_xkb.h | 7 +- .../keycodes/platform_key_map_win_unittest.cc | 3 +- .../ozone/evdev/capture_device_capabilities.py | 2 +- .../ui/events/ozone/evdev/capture_test_events.py | 2 +- .../ui/events/ozone/evdev/event_device_info.cc | 15 + .../ozone/evdev/explain_proc_bus_input_devices.py | 2 +- .../evdev/libgestures_glue/gesture_feedback.cc | 5 +- .../events/ozone/layout/keyboard_layout_engine.h | 1 - .../layout/keyboard_layout_engine_unittest.cc | 2 +- .../layout/stub/stub_keyboard_layout_engine.cc | 3 +- .../ozone/layout/xkb/xkb_keyboard_layout_engine.cc | 43 +- .../ozone/layout/xkb/xkb_keyboard_layout_engine.h | 11 +- .../xkb/xkb_keyboard_layout_engine_unittest.cc | 14 +- .../platform/x11/x11_hotplug_event_handler.cc | 19 +- chromium/ui/events/win/events_win_utils.h | 4 +- chromium/ui/events/x/x11_event_translation.cc | 10 +- chromium/ui/file_manager/BUILD.gn | 192 ++- .../ui/file_manager/audio_player/elements/BUILD.gn | 3 - chromium/ui/file_manager/audio_player/js/BUILD.gn | 50 +- chromium/ui/file_manager/base/js/BUILD.gn | 213 --- .../tools/tests/empty_dependency_list_expected.gn | 2 +- .../tests/single_line_dependency_list_expected.gn | 2 +- chromium/ui/file_manager/externs/BUILD.gn | 190 --- .../ui/file_manager/externs/background/BUILD.gn | 158 -- chromium/ui/file_manager/file_manager/BUILD.gn | 1 + .../file_manager/background/js/BUILD.gn | 389 ++--- .../file_manager/file_manager/common/js/BUILD.gn | 286 +++- .../file_manager/file_manager/cws_widget/BUILD.gn | 1 + .../ui/file_manager/file_manager/externs/BUILD.gn | 193 +++ .../file_manager/externs/background/BUILD.gn | 147 ++ .../file_manager/foreground/elements/BUILD.gn | 12 +- .../file_manager/foreground/js/BUILD.gn | 456 +++--- .../file_manager/foreground/js/metadata/BUILD.gn | 81 +- .../file_manager/foreground/js/ui/BUILD.gn | 165 +- .../ui/file_manager/file_manager/test/BUILD.gn | 106 -- .../ui/file_manager/file_manager/test/js/BUILD.gn | 30 - chromium/ui/file_manager/gallery/js/BUILD.gn | 25 +- .../file_manager/gallery/js/image_editor/BUILD.gn | 13 +- chromium/ui/file_manager/image_loader/BUILD.gn | 40 +- .../ui/file_manager/integration_tests/BUILD.gn | 2 +- .../integration_tests/file_manager/BUILD.gn | 8 +- chromium/ui/file_manager/video_player/js/BUILD.gn | 68 +- chromium/ui/gfx/BUILD.gn | 6 + chromium/ui/gfx/DEPS | 6 + chromium/ui/gfx/animation/keyframe/BUILD.gn | 1 + .../ui/gfx/animation/keyframe/animation_curve.cc | 1 + .../ui/gfx/animation/keyframe/animation_curve.h | 9 +- .../ui/gfx/animation/keyframe/keyframe_effect.cc | 61 +- .../ui/gfx/animation/keyframe/keyframe_effect.h | 24 +- .../keyframe/keyframed_animation_curve-inl.h | 148 ++ .../keyframe/keyframed_animation_curve.cc | 222 +-- .../animation/keyframe/keyframed_animation_curve.h | 60 + .../keyframe/keyframed_animation_curve_unittest.cc | 92 ++ chromium/ui/gfx/animation/multi_animation.cc | 33 +- chromium/ui/gfx/animation/multi_animation.h | 47 +- .../ui/gfx/animation/multi_animation_unittest.cc | 65 +- chromium/ui/gfx/animation/tween.cc | 3 + chromium/ui/gfx/animation/tween.h | 6 +- chromium/ui/gfx/bidi_line_iterator.cc | 6 +- chromium/ui/gfx/bidi_line_iterator.h | 5 +- chromium/ui/gfx/bidi_line_iterator_unittest.cc | 7 +- chromium/ui/gfx/buffer_types.h | 1 + chromium/ui/gfx/buffer_usage_util.cc | 2 + chromium/ui/gfx/canvas.cc | 8 +- chromium/ui/gfx/canvas.h | 14 +- chromium/ui/gfx/canvas_skia.cc | 24 +- chromium/ui/gfx/canvas_unittest.cc | 4 +- chromium/ui/gfx/color_palette.h | 2 +- chromium/ui/gfx/color_transform_unittest.cc | 2 +- chromium/ui/gfx/decorated_text.h | 4 +- chromium/ui/gfx/delegated_ink_metadata.cc | 24 + chromium/ui/gfx/delegated_ink_metadata.h | 94 ++ chromium/ui/gfx/delegated_ink_point.cc | 20 + chromium/ui/gfx/delegated_ink_point.h | 64 + chromium/ui/gfx/font.h | 1 - chromium/ui/gfx/font_fallback.h | 2 +- chromium/ui/gfx/font_fallback_linux_unittest.cc | 24 +- chromium/ui/gfx/font_fallback_mac_unittest.cc | 6 +- chromium/ui/gfx/font_fallback_skia_unittest.cc | 4 +- chromium/ui/gfx/font_fallback_unittest.cc | 11 +- chromium/ui/gfx/font_fallback_win.cc | 4 +- chromium/ui/gfx/font_fallback_win_unittest.cc | 8 +- chromium/ui/gfx/font_unittest.cc | 3 +- chromium/ui/gfx/geometry/mojom/geometry.mojom | 1 + chromium/ui/gfx/geometry/scroll_offset.h | 4 +- .../ui/gfx/linux/client_native_pixmap_dmabuf.cc | 23 +- .../linux/client_native_pixmap_factory_dmabuf.cc | 1 + chromium/ui/gfx/linux/gbm_defines.h | 1 + chromium/ui/gfx/linux/gbm_util.cc | 8 +- chromium/ui/gfx/mojom/BUILD.gn | 41 + chromium/ui/gfx/mojom/DEPS | 6 + chromium/ui/gfx/mojom/buffer_types.mojom | 1 + chromium/ui/gfx/mojom/buffer_types_mojom_traits.cc | 8 +- chromium/ui/gfx/mojom/buffer_types_mojom_traits.h | 5 + chromium/ui/gfx/mojom/delegated_ink_metadata.mojom | 20 + .../mojom/delegated_ink_metadata_mojom_traits.cc | 35 + .../mojom/delegated_ink_metadata_mojom_traits.h | 70 + chromium/ui/gfx/mojom/delegated_ink_point.mojom | 15 + .../gfx/mojom/delegated_ink_point_mojom_traits.cc | 18 + .../gfx/mojom/delegated_ink_point_mojom_traits.h | 36 + chromium/ui/gfx/mojom/native_handle_types.mojom | 16 +- chromium/ui/gfx/render_text.cc | 64 +- chromium/ui/gfx/render_text.h | 37 +- chromium/ui/gfx/render_text_harfbuzz.cc | 56 +- chromium/ui/gfx/render_text_harfbuzz.h | 10 +- chromium/ui/gfx/render_text_test_api.h | 2 +- chromium/ui/gfx/render_text_unittest.cc | 718 +++++---- chromium/ui/gfx/rendering_pipeline.cc | 1 - chromium/ui/gfx/rendering_stage_scheduler.cc | 118 +- chromium/ui/gfx/swap_result.h | 3 + chromium/ui/gfx/switches.cc | 4 - chromium/ui/gfx/switches.h | 1 - chromium/ui/gfx/text_elider.cc | 166 +- chromium/ui/gfx/text_elider.h | 38 +- chromium/ui/gfx/text_elider_unittest.cc | 274 ++-- chromium/ui/gfx/text_utils.cc | 22 +- chromium/ui/gfx/text_utils.h | 19 +- chromium/ui/gfx/text_utils_ios.mm | 4 +- chromium/ui/gfx/text_utils_skia.cc | 4 +- chromium/ui/gfx/text_utils_unittest.cc | 35 +- chromium/ui/gfx/utf16_indexing.cc | 6 +- chromium/ui/gfx/utf16_indexing.h | 9 +- chromium/ui/gfx/utf16_indexing_unittest.cc | 5 +- chromium/ui/gfx/win/hwnd_util.cc | 22 +- chromium/ui/gfx/win/msg_util.h | 2 +- chromium/ui/gfx/x/connection.cc | 5 +- chromium/ui/gfx/x/x11_atom_cache.cc | 4 + chromium/ui/gfx/x/xproto_types.cc | 9 +- chromium/ui/gfx/x/xproto_types.h | 3 +- chromium/ui/gl/BUILD.gn | 2 + chromium/ui/gl/DEPS | 3 + chromium/ui/gl/angle_platform_impl.cc | 1 + chromium/ui/gl/child_window_win.cc | 1 + chromium/ui/gl/dc_layer_tree.cc | 85 +- chromium/ui/gl/dc_layer_tree.h | 26 + chromium/ui/gl/delegated_ink_point_renderer_gpu.h | 190 +++ chromium/ui/gl/direct_composition_surface_win.cc | 108 +- chromium/ui/gl/direct_composition_surface_win.h | 18 + .../gl/direct_composition_surface_win_unittest.cc | 7 +- chromium/ui/gl/features.gni | 2 +- chromium/ui/gl/gl_context_egl.cc | 10 +- chromium/ui/gl/gl_image_d3d_unittest.cc | 5 +- chromium/ui/gl/gl_image_egl.cc | 12 + chromium/ui/gl/gl_image_egl_pixmap.cc | 12 +- chromium/ui/gl/gl_image_native_pixmap_unittest.cc | 8 +- chromium/ui/gl/gl_implementation.cc | 171 +- chromium/ui/gl/gl_implementation.h | 50 +- chromium/ui/gl/gl_surface.cc | 17 +- chromium/ui/gl/gl_surface.h | 10 + chromium/ui/gl/gl_surface_egl.cc | 59 +- chromium/ui/gl/gl_surface_egl.h | 1 + chromium/ui/gl/gl_surface_egl_unittest.cc | 6 +- chromium/ui/gl/gl_surface_egl_x11.cc | 41 +- chromium/ui/gl/gl_surface_glx.cc | 14 +- chromium/ui/gl/gl_switches.cc | 1 + chromium/ui/gl/gl_switches.h | 1 + chromium/ui/gl/hdr_metadata_helper_win.cc | 4 +- chromium/ui/gl/hdr_metadata_helper_win.h | 9 +- chromium/ui/gl/init/create_gr_gl_interface.cc | 30 - chromium/ui/gl/init/gl_factory.cc | 65 +- chromium/ui/gl/init/gl_factory.h | 2 +- chromium/ui/gl/init/gl_initializer.h | 2 +- chromium/ui/gl/init/gl_initializer_android.cc | 12 +- chromium/ui/gl/init/gl_initializer_linux_x11.cc | 20 +- chromium/ui/gl/init/gl_initializer_linux_x11.h | 2 +- chromium/ui/gl/init/gl_initializer_mac.cc | 18 +- chromium/ui/gl/init/gl_initializer_ozone.cc | 6 +- chromium/ui/gl/init/gl_initializer_win.cc | 16 +- chromium/ui/gl/init/ozone_util.h | 8 +- chromium/ui/gl/swap_chain_presenter.cc | 65 +- chromium/ui/gl/swap_chain_presenter.h | 4 +- chromium/ui/gtk/BUILD.gn | 62 +- chromium/ui/gtk/DEPS | 1 + chromium/ui/gtk/gdk.sigs | 20 + chromium/ui/gtk/gdk_pixbuf.fragment | 1 - chromium/ui/gtk/gio.sigs | 4 + chromium/ui/gtk/gsk.sigs | 16 + chromium/ui/gtk/gtk.fragment | 1 + chromium/ui/gtk/gtk.sigs | 54 + chromium/ui/gtk/gtk_color_mixers.cc | 42 + chromium/ui/gtk/gtk_color_mixers.h | 23 + chromium/ui/gtk/gtk_compat.cc | 282 ++++ chromium/ui/gtk/gtk_compat.h | 99 ++ chromium/ui/gtk/gtk_key_bindings_handler.cc | 53 +- chromium/ui/gtk/gtk_key_bindings_handler.h | 3 +- chromium/ui/gtk/gtk_types.h | 90 ++ chromium/ui/gtk/gtk_ui.cc | 222 +-- chromium/ui/gtk/gtk_ui.h | 8 +- chromium/ui/gtk/gtk_ui_delegate.h | 13 +- chromium/ui/gtk/gtk_util.cc | 813 ++++++++-- chromium/ui/gtk/gtk_util.h | 92 +- chromium/ui/gtk/input_method_context_impl_gtk.cc | 117 +- chromium/ui/gtk/input_method_context_impl_gtk.h | 26 +- chromium/ui/gtk/log_noop.h | 18 + chromium/ui/gtk/native_theme_gtk.cc | 549 ++----- chromium/ui/gtk/native_theme_gtk.h | 18 +- chromium/ui/gtk/native_theme_gtk_unittest.cc | 96 ++ chromium/ui/gtk/nav_button_provider_gtk.cc | 264 +-- chromium/ui/gtk/printing/print_dialog_gtk.cc | 10 +- chromium/ui/gtk/printing/print_dialog_gtk.h | 4 +- chromium/ui/gtk/printing/printing_gtk_util.cc | 7 +- chromium/ui/gtk/select_file_dialog_impl.h | 2 +- chromium/ui/gtk/select_file_dialog_impl_gtk.cc | 250 +-- chromium/ui/gtk/select_file_dialog_impl_gtk.h | 17 +- chromium/ui/gtk/select_file_dialog_impl_kde.cc | 4 +- chromium/ui/gtk/settings_provider_gsettings.cc | 5 +- chromium/ui/gtk/settings_provider_gtk.cc | 9 +- chromium/ui/gtk/wayland/BUILD.gn | 21 + .../ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc | 91 ++ .../ui/gtk/wayland/gtk_ui_delegate_wayland_base.h | 49 + chromium/ui/gtk/x/gtk_event_loop_x11.cc | 90 +- chromium/ui/gtk/x/gtk_event_loop_x11.h | 23 +- chromium/ui/gtk/x/gtk_ui_delegate_x11.cc | 33 +- chromium/ui/gtk/x/gtk_ui_delegate_x11.h | 7 +- chromium/ui/latency/latency_info.cc | 7 +- chromium/ui/latency/latency_tracker.cc | 121 +- chromium/ui/latency/latency_tracker.h | 11 +- chromium/ui/login/BUILD.gn | 11 - chromium/ui/login/DIR_METADATA | 3 - chromium/ui/login/OWNERS | 9 - chromium/ui/login/bubble.css | 173 -- chromium/ui/login/bubble.js | 433 ----- chromium/ui/login/display_manager.js | 961 ----------- chromium/ui/login/display_manager_types.js | 73 - chromium/ui/login/login_ui_tools.js | 58 - chromium/ui/login/oobe.css | 197 --- chromium/ui/login/screen.js | 212 --- chromium/ui/login/screen_container.css | 147 -- chromium/ui/message_center/BUILD.gn | 1 + chromium/ui/message_center/fake_message_center.cc | 6 +- chromium/ui/message_center/fake_message_center.h | 6 +- chromium/ui/message_center/message_center.h | 6 +- chromium/ui/message_center/message_center_impl.cc | 8 +- chromium/ui/message_center/message_center_impl.h | 10 +- .../message_center/message_center_impl_unittest.cc | 174 +- .../ui/message_center/message_center_observer.h | 3 +- .../message_center_stats_collector.cc | 2 +- .../message_center_stats_collector.h | 2 +- .../message_center/notification_list_unittest.cc | 148 +- .../public/cpp/message_center_constants.h | 13 - .../ui/message_center/public/cpp/notification.cc | 47 +- .../ui/message_center/public/cpp/notification.h | 71 +- .../public/cpp/notification_delegate.cc | 4 +- .../public/cpp/notification_delegate.h | 7 +- .../ui/message_center/public/cpp/notifier_id.h | 1 - .../views/message_popup_collection_unittest.cc | 10 +- chromium/ui/message_center/views/message_view.cc | 23 +- chromium/ui/message_center/views/message_view.h | 8 +- .../views/notification_control_buttons_unittest.cc | 4 +- .../views/notification_header_view.cc | 17 +- .../views/notification_header_view.h | 6 +- .../views/notification_header_view_unittest.cc | 10 +- .../message_center/views/notification_view_md.cc | 69 +- .../ui/message_center/views/notification_view_md.h | 18 +- .../views/notification_view_md_unittest.cc | 72 +- chromium/ui/message_center/views/padded_button.cc | 12 +- .../views/relative_time_formatter.cc | 2 +- .../message_center/views/relative_time_formatter.h | 5 +- .../views/relative_time_formatter_unittest.cc | 38 +- chromium/ui/native_theme/BUILD.gn | 27 +- chromium/ui/native_theme/OWNERS | 1 + chromium/ui/native_theme/common_theme.cc | 592 +++---- chromium/ui/native_theme/common_theme.h | 15 +- chromium/ui/native_theme/native_theme.cc | 255 +-- chromium/ui/native_theme/native_theme.h | 56 +- chromium/ui/native_theme/native_theme_android.cc | 6 +- chromium/ui/native_theme/native_theme_android.h | 5 +- chromium/ui/native_theme/native_theme_aura.cc | 65 +- chromium/ui/native_theme/native_theme_base.cc | 171 +- chromium/ui/native_theme/native_theme_base.h | 34 +- chromium/ui/native_theme/native_theme_color_id.h | 29 +- chromium/ui/native_theme/native_theme_mac.h | 16 +- chromium/ui/native_theme/native_theme_mac.mm | 82 +- chromium/ui/native_theme/native_theme_observer.h | 3 + chromium/ui/native_theme/native_theme_unittest.cc | 125 +- chromium/ui/native_theme/native_theme_utils.cc | 241 +++ chromium/ui/native_theme/native_theme_utils.h | 33 + chromium/ui/native_theme/native_theme_win.cc | 40 +- chromium/ui/native_theme/native_theme_win.h | 13 +- .../overlay_scrollbar_constants_aura.h | 5 - chromium/ui/native_theme/test_native_theme.cc | 15 +- chromium/ui/native_theme/test_native_theme.h | 10 +- chromium/ui/ozone/BUILD.gn | 5 + chromium/ui/ozone/common/egl_util.cc | 7 +- chromium/ui/ozone/common/egl_util.h | 2 +- chromium/ui/ozone/common/gl_ozone_egl.cc | 4 +- chromium/ui/ozone/common/gl_ozone_egl.h | 6 +- .../test/stub_ozone_ui_controls_test_helper.cc | 4 - .../test/stub_ozone_ui_controls_test_helper.h | 1 - chromium/ui/ozone/demo/demo_window.cc | 3 +- chromium/ui/ozone/demo/demo_window.h | 2 +- chromium/ui/ozone/demo/ozone_demo.cc | 1 + chromium/ui/ozone/demo/skia/skia_demo.cc | 1 + chromium/ui/ozone/demo/window_manager.cc | 1 + .../ui/ozone/platform/cast/gl_ozone_egl_cast.cc | 3 +- .../ui/ozone/platform/cast/gl_ozone_egl_cast.h | 3 +- .../ui/ozone/platform/cast/surface_factory_cast.cc | 5 +- .../ui/ozone/platform/cast/surface_factory_cast.h | 2 +- chromium/ui/ozone/platform/drm/BUILD.gn | 1 + .../ozone/platform/drm/gpu/crtc_commit_request.cc | 2 - chromium/ui/ozone/platform/drm/gpu/drm_display.cc | 7 + .../drm/gpu/drm_overlay_validator_unittest.cc | 11 +- chromium/ui/ozone/platform/drm/gpu/drm_thread.cc | 6 +- chromium/ui/ozone/platform/drm/gpu/drm_thread.h | 2 +- chromium/ui/ozone/platform/drm/gpu/drm_window.cc | 14 +- chromium/ui/ozone/platform/drm/gpu/drm_window.h | 12 +- .../ozone/platform/drm/gpu/drm_window_unittest.cc | 5 +- .../ozone/platform/drm/gpu/gbm_surface_factory.cc | 7 +- .../ozone/platform/drm/gpu/gbm_surface_factory.h | 2 +- .../drm/gpu/hardware_display_controller.cc | 90 +- .../platform/drm/gpu/hardware_display_controller.h | 19 +- .../gpu/hardware_display_controller_unittest.cc | 319 ++-- .../drm/gpu/hardware_display_plane_manager.cc | 10 +- .../drm/gpu/hardware_display_plane_manager.h | 4 +- .../gpu/hardware_display_plane_manager_atomic.cc | 9 +- .../ui/ozone/platform/drm/gpu/mock_drm_device.cc | 35 +- .../ui/ozone/platform/drm/gpu/mock_drm_device.h | 10 - .../ui/ozone/platform/drm/gpu/screen_manager.cc | 165 +- .../ui/ozone/platform/drm/gpu/screen_manager.h | 24 +- .../platform/drm/gpu/screen_manager_unittest.cc | 270 +--- chromium/ui/ozone/platform/drm/host/drm_cursor.cc | 26 +- chromium/ui/ozone/platform/drm/host/drm_cursor.h | 10 +- .../platform/drm/host/drm_display_host_manager.cc | 35 +- .../ui/ozone/platform/drm/host/drm_window_host.cc | 2 +- .../ui/ozone/platform/drm/host/drm_window_host.h | 2 +- .../ozone/platform/drm/host/host_cursor_proxy.cc | 7 +- .../ui/ozone/platform/drm/host/host_cursor_proxy.h | 2 +- chromium/ui/ozone/platform/headless/BUILD.gn | 6 + chromium/ui/ozone/platform/headless/DEPS | 1 + .../platform/headless/headless_surface_factory.cc | 7 +- .../platform/headless/headless_surface_factory.h | 2 +- .../platform/headless/ozone_platform_headless.cc | 11 + chromium/ui/ozone/platform/scenic/BUILD.gn | 23 +- .../ui/ozone/platform/scenic/safe_presenter.cc | 56 + chromium/ui/ozone/platform/scenic/safe_presenter.h | 54 + .../ozone/platform/scenic/scenic_overlay_view.cc | 11 +- .../ui/ozone/platform/scenic/scenic_overlay_view.h | 3 + .../ui/ozone/platform/scenic/scenic_surface.cc | 26 +- chromium/ui/ozone/platform/scenic/scenic_surface.h | 9 + .../platform/scenic/scenic_surface_factory.cc | 8 +- .../ozone/platform/scenic/scenic_surface_factory.h | 2 +- chromium/ui/ozone/platform/scenic/scenic_window.cc | 74 +- chromium/ui/ozone/platform/scenic/scenic_window.h | 29 +- .../ozone/platform/scenic/scenic_window_canvas.cc | 5 +- .../platform/scenic/scenic_window_unittest.cc | 81 + .../platform/scenic/sysmem_buffer_collection.cc | 6 +- .../scenic/vulkan_implementation_scenic.cc | 3 +- chromium/ui/ozone/platform/wayland/BUILD.gn | 65 +- chromium/ui/ozone/platform/wayland/DEPS | 1 + .../ui/ozone/platform/wayland/common/data_util.cc | 16 +- .../wayland/emulate/wayland_input_emulate.cc | 363 +++++ .../wayland/emulate/wayland_input_emulate.h | 165 ++ .../wayland/gpu/gbm_surfaceless_wayland.cc | 4 + .../platform/wayland/gpu/gbm_surfaceless_wayland.h | 1 + .../platform/wayland/gpu/gl_surface_wayland.cc | 28 +- .../platform/wayland/gpu/gl_surface_wayland.h | 11 +- .../wayland/gpu/wayland_buffer_manager_gpu.cc | 11 +- .../wayland/gpu/wayland_buffer_manager_gpu.h | 8 +- .../wayland/gpu/wayland_surface_factory.cc | 14 +- .../platform/wayland/gpu/wayland_surface_factory.h | 2 +- .../gpu/wayland_surface_factory_unittest.cc | 12 +- chromium/ui/ozone/platform/wayland/host/DEPS | 2 + .../wayland/host/gtk_ui_delegate_wayland.cc | 75 +- .../wayland/host/gtk_ui_delegate_wayland.h | 28 +- .../platform/wayland/host/proxy/wayland_proxy.cc | 28 + .../platform/wayland/host/proxy/wayland_proxy.h | 88 + .../wayland/host/proxy/wayland_proxy_impl.cc | 105 ++ .../wayland/host/proxy/wayland_proxy_impl.h | 53 + .../platform/wayland/host/shell_toplevel_wrapper.h | 5 +- .../wayland/host/wayland_auxiliary_window.cc | 63 +- .../wayland/host/wayland_auxiliary_window.h | 6 +- .../host/wayland_buffer_manager_connector.cc | 3 +- .../wayland/host/wayland_buffer_manager_host.cc | 88 +- .../wayland/host/wayland_buffer_manager_host.h | 1 + .../platform/wayland/host/wayland_clipboard.cc | 58 +- .../platform/wayland/host/wayland_clipboard.h | 1 - .../wayland/host/wayland_clipboard_unittest.cc | 80 +- .../platform/wayland/host/wayland_connection.cc | 46 +- .../platform/wayland/host/wayland_connection.h | 15 +- .../ozone/platform/wayland/host/wayland_cursor.cc | 86 +- .../ozone/platform/wayland/host/wayland_cursor.h | 26 +- .../wayland/host/wayland_cursor_factory.cc | 27 +- .../platform/wayland/host/wayland_cursor_factory.h | 10 +- .../host/wayland_cursor_factory_unittest.cc | 12 +- .../platform/wayland/host/wayland_data_device.cc | 1 + .../wayland/host/wayland_data_drag_controller.cc | 1 + .../host/wayland_data_drag_controller_unittest.cc | 10 +- .../platform/wayland/host/wayland_data_source.h | 2 +- .../platform/wayland/host/wayland_event_source.cc | 21 +- .../platform/wayland/host/wayland_event_source.h | 3 +- .../wayland/host/wayland_input_method_context.cc | 34 +- .../wayland/host/wayland_input_method_context.h | 4 +- .../host/wayland_input_method_context_unittest.cc | 2 +- .../platform/wayland/host/wayland_keyboard.cc | 121 +- .../ozone/platform/wayland/host/wayland_keyboard.h | 31 +- .../wayland/host/wayland_keyboard_unittest.cc | 4 + .../ozone/platform/wayland/host/wayland_output.cc | 15 +- .../ozone/platform/wayland/host/wayland_output.h | 2 + .../wayland/host/wayland_output_manager.cc | 27 +- .../platform/wayland/host/wayland_output_manager.h | 9 +- .../ozone/platform/wayland/host/wayland_pointer.h | 3 + .../wayland/host/wayland_pointer_unittest.cc | 7 + .../ozone/platform/wayland/host/wayland_popup.cc | 14 +- .../ui/ozone/platform/wayland/host/wayland_popup.h | 4 +- .../ozone/platform/wayland/host/wayland_screen.cc | 32 +- .../ozone/platform/wayland/host/wayland_screen.h | 2 + .../wayland/host/wayland_screen_unittest.cc | 8 +- .../ozone/platform/wayland/host/wayland_surface.cc | 10 +- .../wayland/host/wayland_toplevel_window.cc | 94 +- .../wayland/host/wayland_toplevel_window.h | 17 +- .../ozone/platform/wayland/host/wayland_window.cc | 158 +- .../ozone/platform/wayland/host/wayland_window.h | 28 +- .../wayland_window_drag_controller_unittest.cc | 19 +- .../wayland/host/wayland_window_factory.cc | 29 +- .../wayland/host/wayland_window_manager.cc | 2 +- .../host/wayland_window_manager_unittests.cc | 5 +- .../wayland/host/wayland_window_unittest.cc | 359 ++++- .../wayland/host/wayland_zcr_cursor_shapes.cc | 4 + .../wayland/host/xdg_surface_wrapper_impl.cc | 1 + .../wayland/host/xdg_surface_wrapper_impl.h | 1 - .../wayland/host/xdg_toplevel_wrapper_impl.cc | 3 +- .../wayland/host/xdg_toplevel_wrapper_impl.h | 2 +- .../platform/wayland/host/zwp_text_input_wrapper.h | 4 +- .../wayland/host/zwp_text_input_wrapper_v1.cc | 3 +- .../wayland/host/zwp_text_input_wrapper_v1.h | 2 +- .../wayland/host/zxdg_surface_v6_wrapper_impl.cc | 2 + .../wayland/host/zxdg_surface_v6_wrapper_impl.h | 1 - .../wayland/host/zxdg_toplevel_v6_wrapper_impl.cc | 3 +- .../wayland/host/zxdg_toplevel_v6_wrapper_impl.h | 2 +- .../platform/wayland/ozone_platform_wayland.cc | 15 +- .../test/wayland_ozone_ui_controls_test_helper.cc | 301 ++++ .../test/wayland_ozone_ui_controls_test_helper.h | 74 + .../ui/ozone/platform/wayland/test/wayland_test.cc | 17 +- .../wayland/wayland_buffer_manager_unittest.cc | 14 +- .../platform/windows/windows_surface_factory.cc | 7 +- .../platform/windows/windows_surface_factory.h | 2 +- chromium/ui/ozone/platform/x11/BUILD.gn | 6 + chromium/ui/ozone/platform/x11/gl_ozone_glx.cc | 2 +- chromium/ui/ozone/platform/x11/gl_ozone_glx.h | 3 +- .../ui/ozone/platform/x11/ozone_platform_x11.cc | 35 +- .../ui/ozone/platform/x11/x11_canvas_surface.cc | 6 +- .../ui/ozone/platform/x11/x11_clipboard_ozone.cc | 405 +---- .../ui/ozone/platform/x11/x11_clipboard_ozone.h | 71 +- .../x11/x11_global_shortcut_listener_ozone.cc | 53 + .../x11/x11_global_shortcut_listener_ozone.h | 46 + chromium/ui/ozone/platform/x11/x11_menu_utils.cc | 2 +- .../x11/x11_ozone_ui_controls_test_helper.cc | 4 + .../x11/x11_ozone_ui_controls_test_helper.h | 1 + chromium/ui/ozone/platform/x11/x11_screen_ozone.cc | 38 +- chromium/ui/ozone/platform/x11/x11_screen_ozone.h | 5 + .../ui/ozone/platform/x11/x11_surface_factory.cc | 41 +- .../ui/ozone/platform/x11/x11_surface_factory.h | 2 +- chromium/ui/ozone/platform/x11/x11_utils.cc | 19 + chromium/ui/ozone/platform/x11/x11_utils.h | 24 + .../platform/x11/x11_window_ozone_unittest.cc | 2 +- chromium/ui/ozone/public/gl_ozone.h | 2 +- chromium/ui/ozone/public/mojom/device_cursor.mojom | 6 +- .../mojom/wayland/wayland_buffer_manager.mojom | 3 + chromium/ui/ozone/public/ozone_gpu_test_helper.cc | 1 + chromium/ui/ozone/public/ozone_platform.cc | 11 + chromium/ui/ozone/public/ozone_platform.h | 10 + .../ozone/public/ozone_ui_controls_test_helper.h | 5 + chromium/ui/ozone/public/platform_clipboard.h | 12 +- .../public/platform_global_shortcut_listener.cc | 22 + .../public/platform_global_shortcut_listener.h | 69 + chromium/ui/ozone/public/platform_screen.cc | 11 + chromium/ui/ozone/public/platform_screen.h | 8 + chromium/ui/ozone/public/platform_utils.h | 32 + chromium/ui/ozone/public/surface_factory_ozone.cc | 3 +- chromium/ui/ozone/public/surface_factory_ozone.h | 2 +- .../ui/ozone/test/mock_platform_window_delegate.cc | 5 + .../ui/ozone/test/mock_platform_window_delegate.h | 5 +- .../common/platform_window_defaults.h | 4 +- chromium/ui/platform_window/platform_window.h | 5 +- .../ui/platform_window/platform_window_delegate.cc | 9 + .../ui/platform_window/platform_window_delegate.h | 42 +- chromium/ui/platform_window/stub/stub_window.cc | 4 +- chromium/ui/platform_window/stub/stub_window.h | 2 +- chromium/ui/platform_window/win/win_window.cc | 5 +- chromium/ui/platform_window/win/win_window.h | 3 +- chromium/ui/platform_window/wm/BUILD.gn | 1 + chromium/ui/platform_window/x11/BUILD.gn | 4 + chromium/ui/platform_window/x11/DEPS | 1 + chromium/ui/platform_window/x11/x11_window.cc | 1694 ++++++++++++++++++-- chromium/ui/platform_window/x11/x11_window.h | 326 +++- .../pointers/sb_horizontal_double_arrow_block.png | Bin 0 -> 789 bytes .../sb_horizontal_double_arrow_block_big.png | Bin 0 -> 2105 bytes .../pointers/sb_vertical_double_arrow_block.png | Bin 0 -> 814 bytes .../sb_vertical_double_arrow_block_big.png | Bin 0 -> 2135 bytes .../common/pointers/top_left_corner_block.png | Bin 0 -> 865 bytes .../common/pointers/top_left_corner_block_big.png | Bin 0 -> 2464 bytes .../common/pointers/top_right_corner_block.png | Bin 0 -> 844 bytes .../common/pointers/top_right_corner_block_big.png | Bin 0 -> 2445 bytes .../pointers/sb_horizontal_double_arrow_block.png | Bin 0 -> 1819 bytes .../pointers/sb_vertical_double_arrow_block.png | Bin 0 -> 1789 bytes .../common/pointers/top_left_corner_block.png | Bin 0 -> 1817 bytes .../common/pointers/top_right_corner_block.png | Bin 0 -> 1777 bytes chromium/ui/resources/ui_resources.grd | 8 + .../ui/shell_dialogs/execute_select_file_win.cc | 30 +- .../ui/shell_dialogs/execute_select_file_win.h | 8 +- .../ui/shell_dialogs/fake_select_file_dialog.cc | 2 +- .../ui/shell_dialogs/fake_select_file_dialog.h | 9 +- chromium/ui/shell_dialogs/select_file_dialog.cc | 2 +- chromium/ui/shell_dialogs/select_file_dialog.h | 7 +- .../ui/shell_dialogs/select_file_dialog_android.cc | 8 +- .../ui/shell_dialogs/select_file_dialog_android.h | 2 +- .../ui/shell_dialogs/select_file_dialog_lacros.cc | 2 +- .../ui/shell_dialogs/select_file_dialog_lacros.h | 2 +- chromium/ui/shell_dialogs/select_file_dialog_mac.h | 2 +- .../ui/shell_dialogs/select_file_dialog_mac.mm | 2 +- .../select_file_dialog_mac_unittest.mm | 52 +- .../ui/shell_dialogs/select_file_dialog_win.cc | 51 +- chromium/ui/shell_dialogs/select_file_dialog_win.h | 4 +- .../select_file_dialog_win_unittest.cc | 21 +- chromium/ui/shell_dialogs/selected_file_info.h | 2 +- chromium/ui/snapshot/BUILD.gn | 9 + chromium/ui/snapshot/snapshot_async.cc | 6 +- chromium/ui/strings/BUILD.gn | 4 +- chromium/ui/strings/translations/ui_strings_de.xtb | 2 +- chromium/ui/strings/translations/ui_strings_es.xtb | 2 +- chromium/ui/strings/translations/ui_strings_fa.xtb | 2 +- .../ui/strings/translations/ui_strings_fr-CA.xtb | 2 +- chromium/ui/strings/translations/ui_strings_it.xtb | 14 +- chromium/ui/strings/translations/ui_strings_ky.xtb | 4 +- chromium/ui/strings/translations/ui_strings_ne.xtb | 4 +- .../touch_selection/touch_handle_drawable_aura.cc | 1 - .../touch_selection/touch_selection_controller.cc | 14 +- .../touch_selection/touch_selection_menu_runner.h | 2 +- chromium/ui/views/BUILD.gn | 10 + chromium/ui/views/DEPS | 1 + chromium/ui/views/OWNERS | 1 + .../ui/views/accessibility/ax_aura_obj_cache.cc | 29 +- .../ui/views/accessibility/ax_aura_obj_cache.h | 2 + .../accessibility/ax_aura_obj_cache_unittest.cc | 8 +- .../ui/views/accessibility/ax_root_obj_wrapper.cc | 4 + .../ax_system_caret_win_interactive_uitest.cc | 4 +- .../ui/views/accessibility/ax_tree_source_views.h | 2 +- .../accessibility/ax_tree_source_views_unittest.cc | 19 +- .../ui/views/accessibility/ax_view_obj_wrapper.cc | 12 +- chromium/ui/views/accessibility/ax_virtual_view.h | 2 +- .../views/accessibility/ax_window_obj_wrapper.cc | 75 +- .../ui/views/accessibility/view_accessibility.cc | 36 +- .../ui/views/accessibility/view_accessibility.h | 15 +- .../view_ax_platform_node_delegate.cc | 8 +- .../accessibility/view_ax_platform_node_delegate.h | 6 +- ...ax_platform_node_delegate_auralinux_unittest.cc | 12 +- .../view_ax_platform_node_delegate_unittest.cc | 33 +- .../view_ax_platform_node_delegate_win_unittest.cc | 14 +- chromium/ui/views/accessible_pane_view_unittest.cc | 2 +- chromium/ui/views/border.h | 12 +- chromium/ui/views/border_unittest.cc | 2 +- .../bubble/bubble_dialog_delegate_view_unittest.cc | 12 +- .../ui/views/bubble/bubble_dialog_model_host.cc | 6 +- .../ui/views/bubble/bubble_dialog_model_host.h | 2 +- chromium/ui/views/bubble/bubble_frame_view.cc | 14 +- chromium/ui/views/bubble/bubble_frame_view.h | 2 +- .../ui/views/bubble/bubble_frame_view_unittest.cc | 14 +- chromium/ui/views/bubble/info_bubble.cc | 2 +- chromium/ui/views/bubble/info_bubble.h | 4 +- chromium/ui/views/bubble/info_bubble_unittest.cc | 16 +- chromium/ui/views/bubble/tooltip_icon.cc | 2 +- chromium/ui/views/bubble/tooltip_icon.h | 6 +- chromium/ui/views/button_drag_utils.cc | 4 +- chromium/ui/views/button_drag_utils.h | 7 +- .../views/cocoa/bridged_native_widget_unittest.mm | 32 +- .../views/cocoa/drag_drop_client_mac_unittest.mm | 8 +- .../views/cocoa/native_widget_mac_ns_window_host.h | 8 +- .../cocoa/native_widget_mac_ns_window_host.mm | 25 +- chromium/ui/views/cocoa/text_input_host.h | 8 +- chromium/ui/views/cocoa/text_input_host.mm | 16 +- .../views/color_chooser/color_chooser_unittest.cc | 2 +- .../ui/views/color_chooser/color_chooser_view.cc | 70 +- .../ui/views/color_chooser/color_chooser_view.h | 2 +- chromium/ui/views/controls/button/button.cc | 27 +- chromium/ui/views/controls/button/button.h | 20 +- .../ui/views/controls/button/button_unittest.cc | 6 +- chromium/ui/views/controls/button/checkbox.cc | 10 +- chromium/ui/views/controls/button/checkbox.h | 6 +- .../ui/views/controls/button/checkbox_unittest.cc | 2 +- chromium/ui/views/controls/button/image_button.cc | 38 +- chromium/ui/views/controls/button/image_button.h | 18 +- .../views/controls/button/image_button_factory.cc | 14 +- .../views/controls/button/image_button_factory.h | 6 +- .../button/image_button_factory_unittest.cc | 9 + chromium/ui/views/controls/button/label_button.cc | 26 +- chromium/ui/views/controls/button/label_button.h | 10 +- .../ui/views/controls/button/label_button_label.cc | 2 +- .../ui/views/controls/button/label_button_label.h | 5 +- .../controls/button/label_button_label_unittest.cc | 7 +- .../views/controls/button/label_button_unittest.cc | 53 +- .../ui/views/controls/button/md_text_button.cc | 43 +- chromium/ui/views/controls/button/md_text_button.h | 6 +- .../controls/button/md_text_button_unittest.cc | 6 +- chromium/ui/views/controls/button/menu_button.cc | 2 +- chromium/ui/views/controls/button/menu_button.h | 5 +- .../views/controls/button/menu_button_unittest.cc | 3 +- chromium/ui/views/controls/button/radio_button.cc | 2 +- chromium/ui/views/controls/button/radio_button.h | 5 +- .../views/controls/button/radio_button_unittest.cc | 12 +- chromium/ui/views/controls/button/toggle_button.cc | 10 +- chromium/ui/views/controls/combobox/combobox.cc | 42 +- chromium/ui/views/controls/combobox/combobox.h | 20 +- .../views/controls/combobox/combobox_unittest.cc | 20 +- .../controls/combobox/empty_combobox_model.cc | 7 +- .../views/controls/combobox/empty_combobox_model.h | 2 +- chromium/ui/views/controls/dot_indicator.h | 5 +- .../editable_combobox/editable_combobox.cc | 36 +- .../controls/editable_combobox/editable_combobox.h | 14 +- .../editable_combobox_unittest.cc | 175 +- chromium/ui/views/controls/image_view.cc | 25 +- chromium/ui/views/controls/image_view.h | 18 +- chromium/ui/views/controls/image_view_unittest.cc | 2 +- chromium/ui/views/controls/label.cc | 42 +- chromium/ui/views/controls/label.h | 34 +- chromium/ui/views/controls/label_perftest.cc | 4 +- chromium/ui/views/controls/label_unittest.cc | 162 +- chromium/ui/views/controls/link.cc | 4 +- chromium/ui/views/controls/link.h | 4 +- chromium/ui/views/controls/link_unittest.cc | 3 +- chromium/ui/views/controls/menu/menu_config.cc | 2 +- chromium/ui/views/controls/menu/menu_config.h | 8 +- chromium/ui/views/controls/menu/menu_controller.cc | 42 +- chromium/ui/views/controls/menu/menu_controller.h | 14 +- .../controls/menu/menu_controller_unittest.cc | 86 +- chromium/ui/views/controls/menu/menu_delegate.cc | 22 +- chromium/ui/views/controls/menu/menu_delegate.h | 20 +- chromium/ui/views/controls/menu/menu_host.cc | 37 +- chromium/ui/views/controls/menu/menu_host.h | 5 +- chromium/ui/views/controls/menu/menu_item_view.cc | 130 +- chromium/ui/views/controls/menu/menu_item_view.h | 53 +- .../views/controls/menu/menu_item_view_unittest.cc | 74 +- .../ui/views/controls/menu/menu_model_adapter.cc | 8 +- .../ui/views/controls/menu/menu_model_adapter.h | 2 +- .../controls/menu/menu_model_adapter_unittest.cc | 4 +- chromium/ui/views/controls/menu/menu_runner.cc | 6 +- chromium/ui/views/controls/menu/menu_runner.h | 9 +- .../controls/menu/menu_runner_cocoa_unittest.mm | 7 +- .../ui/views/controls/menu/menu_runner_impl.cc | 6 +- chromium/ui/views/controls/menu/menu_runner_impl.h | 3 +- .../controls/menu/menu_runner_impl_adapter.cc | 15 +- .../views/controls/menu/menu_runner_impl_adapter.h | 3 +- .../views/controls/menu/menu_runner_impl_cocoa.h | 3 +- .../views/controls/menu/menu_runner_impl_cocoa.mm | 3 +- .../controls/menu/menu_runner_impl_interface.h | 3 +- .../ui/views/controls/menu/menu_runner_unittest.cc | 67 +- .../controls/menu/menu_scroll_view_container.cc | 71 +- .../controls/menu/menu_scroll_view_container.h | 7 + chromium/ui/views/controls/menu/native_menu_win.cc | 15 +- chromium/ui/views/controls/menu/native_menu_win.h | 6 +- chromium/ui/views/controls/menu/new_badge.cc | 6 +- chromium/ui/views/controls/menu/new_badge.h | 5 +- chromium/ui/views/controls/menu/submenu_view.cc | 10 +- chromium/ui/views/controls/menu/submenu_view.h | 7 +- chromium/ui/views/controls/message_box_view.cc | 33 +- chromium/ui/views/controls/message_box_view.h | 12 +- .../ui/views/controls/message_box_view_unittest.cc | 27 +- .../ui/views/controls/native/native_view_host.cc | 4 + chromium/ui/views/controls/prefix_delegate.h | 2 +- chromium/ui/views/controls/prefix_selector.cc | 16 +- chromium/ui/views/controls/prefix_selector.h | 14 +- .../ui/views/controls/prefix_selector_unittest.cc | 28 +- .../ui/views/controls/progress_bar_unittest.cc | 2 +- .../views/controls/scrollbar/overlay_scroll_bar.cc | 10 +- chromium/ui/views/controls/scrollbar/scroll_bar.cc | 2 +- chromium/ui/views/controls/slider.cc | 16 +- chromium/ui/views/controls/styled_label.cc | 14 +- chromium/ui/views/controls/styled_label.h | 12 +- .../ui/views/controls/styled_label_unittest.cc | 19 +- .../ui/views/controls/tabbed_pane/tabbed_pane.cc | 42 +- .../ui/views/controls/tabbed_pane/tabbed_pane.h | 16 +- .../tabbed_pane_accessibility_mac_unittest.mm | 4 +- .../controls/tabbed_pane/tabbed_pane_unittest.cc | 37 +- chromium/ui/views/controls/table/table_view.cc | 30 +- chromium/ui/views/controls/table/table_view.h | 2 +- .../ui/views/controls/table/table_view_unittest.cc | 59 +- .../ui/views/controls/table/test_table_model.cc | 2 +- .../ui/views/controls/table/test_table_model.h | 2 +- .../views/controls/textarea/textarea_unittest.cc | 20 +- chromium/ui/views/controls/textfield/textfield.cc | 63 +- chromium/ui/views/controls/textfield/textfield.h | 54 +- .../controls/textfield/textfield_controller.h | 4 +- .../ui/views/controls/textfield/textfield_model.cc | 80 +- .../ui/views/controls/textfield/textfield_model.h | 40 +- .../controls/textfield/textfield_model_unittest.cc | 387 +++-- .../views/controls/textfield/textfield_unittest.cc | 320 ++-- .../views/controls/textfield/textfield_unittest.h | 12 +- chromium/ui/views/controls/tree/tree_view.cc | 6 +- chromium/ui/views/controls/tree/tree_view.h | 4 +- .../controls/tree/tree_view_drawing_provider.cc | 4 +- .../controls/tree/tree_view_drawing_provider.h | 5 +- .../ui/views/controls/tree/tree_view_unittest.cc | 24 +- .../views_text_services_context_menu_mac.mm | 12 +- .../ui/views/controls/webview/web_dialog_view.cc | 19 +- .../ui/views/controls/webview/web_dialog_view.h | 9 +- chromium/ui/views/controls/webview/webview.cc | 10 +- chromium/ui/views/controls/webview/webview.h | 4 - .../ui/views/controls/webview/webview_unittest.cc | 19 + chromium/ui/views/corewm/tooltip.h | 31 +- chromium/ui/views/corewm/tooltip_aura.cc | 77 +- chromium/ui/views/corewm/tooltip_aura.h | 14 +- chromium/ui/views/corewm/tooltip_controller.cc | 347 ++-- chromium/ui/views/corewm/tooltip_controller.h | 119 +- .../views/corewm/tooltip_controller_test_helper.cc | 44 +- .../views/corewm/tooltip_controller_test_helper.h | 29 +- .../ui/views/corewm/tooltip_controller_unittest.cc | 503 ++++-- chromium/ui/views/corewm/tooltip_state_manager.cc | 145 ++ chromium/ui/views/corewm/tooltip_state_manager.h | 137 ++ chromium/ui/views/corewm/tooltip_win.cc | 23 +- chromium/ui/views/corewm/tooltip_win.h | 16 +- chromium/ui/views/examples/BUILD.gn | 3 + chromium/ui/views/examples/DEPS | 1 + chromium/ui/views/examples/README.md | 1 + chromium/ui/views/examples/ax_example.cc | 4 +- chromium/ui/views/examples/box_layout_example.cc | 25 +- chromium/ui/views/examples/box_layout_example.h | 2 +- chromium/ui/views/examples/bubble_example.cc | 40 +- chromium/ui/views/examples/button_example.cc | 61 +- chromium/ui/views/examples/button_sticker_sheet.cc | 2 +- chromium/ui/views/examples/checkbox_example.cc | 2 +- .../ui/views/examples/colored_dialog_example.cc | 10 +- .../ui/views/examples/colored_dialog_example.h | 6 +- chromium/ui/views/examples/combobox_example.cc | 2 +- chromium/ui/views/examples/create_examples.cc | 2 + chromium/ui/views/examples/dialog_example.cc | 20 +- chromium/ui/views/examples/dialog_example.h | 2 +- .../ui/views/examples/example_combobox_model.cc | 2 +- .../ui/views/examples/example_combobox_model.h | 2 +- chromium/ui/views/examples/examples_window.cc | 6 +- chromium/ui/views/examples/flex_layout_example.cc | 26 +- chromium/ui/views/examples/flex_layout_example.h | 2 +- chromium/ui/views/examples/label_example.cc | 40 +- chromium/ui/views/examples/label_example.h | 2 +- chromium/ui/views/examples/layout_example_base.cc | 18 +- chromium/ui/views/examples/layout_example_base.h | 10 +- .../views/examples/login_bubble_dialog_example.cc | 10 +- .../views/examples/login_bubble_dialog_example.h | 11 +- chromium/ui/views/examples/menu_example.cc | 4 +- chromium/ui/views/examples/multiline_example.cc | 14 +- chromium/ui/views/examples/multiline_example.h | 2 +- chromium/ui/views/examples/native_theme_example.cc | 3 +- chromium/ui/views/examples/notification_example.cc | 90 ++ chromium/ui/views/examples/notification_example.h | 27 + chromium/ui/views/examples/progress_bar_example.cc | 4 +- chromium/ui/views/examples/slider_example.cc | 29 +- chromium/ui/views/examples/slider_example.h | 6 +- chromium/ui/views/examples/tabbed_pane_example.cc | 118 +- chromium/ui/views/examples/tabbed_pane_example.h | 26 +- chromium/ui/views/examples/table_example.cc | 22 +- chromium/ui/views/examples/table_example.h | 4 +- chromium/ui/views/examples/text_example.cc | 27 +- chromium/ui/views/examples/textfield_example.cc | 16 +- .../ui/views/examples/toggle_button_example.cc | 14 +- chromium/ui/views/examples/toggle_button_example.h | 6 +- chromium/ui/views/examples/tree_view_example.cc | 2 +- chromium/ui/views/examples/vector_example.cc | 4 +- .../ui/views/examples/views_examples_resources.grd | 11 + chromium/ui/views/examples/widget_example.cc | 2 +- chromium/ui/views/examples/widget_example.h | 2 +- chromium/ui/views/focus/focus_manager.cc | 4 + chromium/ui/views/focus/focus_manager_unittest.cc | 54 + .../ui/views/focus/focus_traversal_unittest.cc | 60 +- chromium/ui/views/image_model_utils.cc | 25 + chromium/ui/views/image_model_utils.h | 26 + chromium/ui/views/image_model_utils_unittest.cc | 35 + chromium/ui/views/layout/box_layout_view.cc | 30 +- chromium/ui/views/layout/flex_layout_unittest.cc | 3 +- chromium/ui/views/layout/flex_layout_view.cc | 21 +- chromium/ui/views/layout/layout_provider.cc | 29 +- chromium/ui/views/layout/layout_provider.h | 18 +- chromium/ui/views/linux_ui/status_icon_linux.h | 7 +- chromium/ui/views/metadata/metadata_types.cc | 2 +- chromium/ui/views/metadata/metadata_types.h | 7 +- chromium/ui/views/metadata/metadata_unittest.cc | 29 +- chromium/ui/views/metadata/property_metadata.h | 13 +- chromium/ui/views/metadata/type_conversion.cc | 441 +++-- chromium/ui/views/metadata/type_conversion.h | 100 +- .../ui/views/metadata/type_conversion_unittest.cc | 84 +- chromium/ui/views/metadata/view_factory.h | 2 +- chromium/ui/views/metadata/view_factory_internal.h | 1 - .../ui/views/metadata/view_factory_unittest.cc | 59 +- chromium/ui/views/style/platform_style.cc | 2 +- chromium/ui/views/style/platform_style.h | 2 +- chromium/ui/views/style/platform_style_mac.mm | 2 +- .../test/ui_controls_factory_desktop_aura_ozone.cc | 8 +- .../touchui/touch_selection_controller_impl.cc | 15 +- .../touchui/touch_selection_controller_impl.h | 2 +- .../touch_selection_controller_impl_unittest.cc | 89 +- .../touch_selection_menu_runner_views_unittest.cc | 4 +- .../ui/views/touchui/touch_selection_menu_views.cc | 17 +- .../ui/views/touchui/touch_selection_menu_views.h | 2 +- chromium/ui/views/view.cc | 24 +- chromium/ui/views/view.h | 16 +- chromium/ui/views/view_unittest.cc | 19 +- chromium/ui/views/views_delegate.cc | 4 +- chromium/ui/views/views_delegate.h | 5 +- chromium/ui/views/views_features.cc | 14 +- chromium/ui/views/views_features.h | 4 +- .../views/widget/ax_native_widget_mac_unittest.mm | 18 +- .../desktop_aura/desktop_drag_drop_client_ozone.cc | 2 +- .../desktop_drag_drop_client_ozone_unittest.cc | 11 +- .../desktop_aura/desktop_native_widget_aura.cc | 7 +- .../desktop_aura/desktop_native_widget_aura.h | 2 +- .../desktop_native_widget_aura_unittest.cc | 4 +- .../widget/desktop_aura/desktop_screen_linux.cc | 43 +- .../widget/desktop_aura/desktop_screen_x11.cc | 9 + .../views/widget/desktop_aura/desktop_screen_x11.h | 2 + .../widget/desktop_aura/desktop_window_tree_host.h | 2 +- .../desktop_aura/desktop_window_tree_host_linux.cc | 21 +- ...op_window_tree_host_linux_interactive_uitest.cc | 131 +- .../desktop_window_tree_host_platform.cc | 18 +- .../desktop_window_tree_host_platform.h | 4 +- .../desktop_aura/desktop_window_tree_host_win.cc | 16 +- .../desktop_aura/desktop_window_tree_host_win.h | 2 +- .../desktop_aura/window_event_filter_linux.cc | 66 +- .../desktop_aura/window_event_filter_linux.h | 8 +- .../desktop_aura/window_move_client_platform.cc | 5 +- .../desktop_aura/x11_drag_drop_client_unittest.cc | 3 +- chromium/ui/views/widget/native_widget_aura.cc | 18 +- chromium/ui/views/widget/native_widget_aura.h | 2 +- chromium/ui/views/widget/native_widget_mac.h | 2 +- chromium/ui/views/widget/native_widget_mac.mm | 30 +- .../ui/views/widget/native_widget_mac_unittest.mm | 35 +- chromium/ui/views/widget/native_widget_private.h | 3 +- chromium/ui/views/widget/root_view.cc | 6 +- chromium/ui/views/widget/root_view.h | 2 +- chromium/ui/views/widget/root_view_unittest.cc | 2 +- chromium/ui/views/widget/tooltip_manager.h | 1 - chromium/ui/views/widget/tooltip_manager_aura.h | 5 +- chromium/ui/views/widget/widget.cc | 14 +- chromium/ui/views/widget/widget.h | 16 +- chromium/ui/views/widget/widget_delegate.cc | 46 +- chromium/ui/views/widget/widget_delegate.h | 16 +- .../ui/views/widget/widget_interactive_uitest.cc | 2 +- chromium/ui/views/widget/widget_unittest.cc | 26 +- chromium/ui/views/win/hwnd_message_handler.cc | 40 +- chromium/ui/views/win/hwnd_message_handler.h | 3 +- chromium/ui/views/win/pen_event_processor.cc | 7 + chromium/ui/views/window/dialog_client_view.cc | 2 +- .../ui/views/window/dialog_client_view_unittest.cc | 35 +- chromium/ui/views/window/dialog_delegate.cc | 8 +- chromium/ui/views/window/dialog_delegate.h | 8 +- .../ui/views/window/dialog_delegate_unittest.cc | 12 +- chromium/ui/views/window/frame_caption_button.cc | 42 +- chromium/ui/views/window/frame_caption_button.h | 26 +- chromium/ui/views/window/non_client_view.cc | 2 +- chromium/ui/views/window/non_client_view.h | 4 +- .../views_content_client_main_parts.cc | 9 +- .../views_content_client_main_parts.h | 3 +- .../views_content_client_main_parts_chromeos.cc | 7 +- ...views_content_client_main_parts_desktop_aura.cc | 7 +- .../views_content_client_main_parts_mac.mm | 7 +- chromium/ui/web_dialogs/web_dialog_delegate.cc | 6 +- chromium/ui/web_dialogs/web_dialog_delegate.h | 19 +- chromium/ui/web_dialogs/web_dialog_ui.h | 1 - .../web_dialog_web_contents_delegate.cc | 7 + .../web_dialogs/web_dialog_web_contents_delegate.h | 18 + chromium/ui/webui/resources/BUILD.gn | 63 +- chromium/ui/webui/resources/cr_components/BUILD.gn | 27 +- .../certificate_manager/certificate_entry.html | 2 +- .../certificate_manager/certificate_manager.js | 2 +- .../chromeos/bluetooth/bluetooth_dialog.js | 12 +- .../cr_components/chromeos/cellular_setup/BUILD.gn | 24 +- .../cellular_setup/activation_code_page.html | 50 +- .../cellular_setup/activation_code_page.js | 186 ++- .../chromeos/cellular_setup/button_bar.html | 7 - .../chromeos/cellular_setup/button_bar.js | 10 +- .../chromeos/cellular_setup/cellular_setup.html | 11 +- .../chromeos/cellular_setup/cellular_setup.js | 62 +- .../chromeos/cellular_setup/cellular_types.js | 4 +- .../cellular_setup/confirmation_code_page.html | 3 +- .../cellular_setup/confirmation_code_page.js | 11 + .../chromeos/cellular_setup/esim_1x.png | Bin 17635 -> 0 bytes .../chromeos/cellular_setup/esim_2x.png | Bin 46473 -> 0 bytes .../chromeos/cellular_setup/esim_flow_ui.html | 3 +- .../chromeos/cellular_setup/esim_flow_ui.js | 282 +++- .../chromeos/cellular_setup/psim_1x.png | Bin 7817 -> 0 bytes .../chromeos/cellular_setup/psim_2x.png | Bin 20999 -> 0 bytes .../chromeos/cellular_setup/psim_flow_ui.html | 4 +- .../chromeos/cellular_setup/psim_flow_ui.js | 188 ++- .../cellular_setup/setup_loading_page.html | 4 +- .../chromeos/cellular_setup/setup_loading_page.js | 8 +- .../cellular_setup/setup_selection_flow.html | 153 -- .../cellular_setup/setup_selection_flow.js | 62 - .../chromeos/cellular_setup/sim_detect_error.svg | 1 + .../chromeos/cellular_setup/subflow_behavior.js | 3 +- .../multidevice_setup/start_setup_page.html | 27 +- .../chromeos/multidevice_setup/ui_page.html | 5 +- .../cr_components/chromeos/network/BUILD.gn | 57 +- .../chromeos/network/cellular_utils.js | 49 +- .../chromeos/network/network_apnlist.html | 50 +- .../chromeos/network/network_apnlist.js | 26 +- .../chromeos/network/network_choose_mobile.html | 5 +- .../chromeos/network/network_choose_mobile.js | 10 +- .../chromeos/network/network_config.html | 13 +- .../chromeos/network/network_config.js | 45 +- .../chromeos/network/network_ip_config.html | 6 +- .../chromeos/network/network_ip_config.js | 10 +- .../chromeos/network/network_list_item.html | 130 +- .../chromeos/network/network_list_item.js | 393 ++++- .../chromeos/network/network_nameservers.html | 3 +- .../chromeos/network/network_nameservers.js | 5 + .../chromeos/network/network_password_input.html | 1 - .../chromeos/network/network_password_input.js | 9 +- .../network/network_property_list_mojo.html | 6 +- .../chromeos/network/network_property_list_mojo.js | 109 +- .../chromeos/network/network_proxy.html | 7 +- .../chromeos/network/network_proxy.js | 28 +- .../chromeos/network/network_siminfo.html | 162 +- .../chromeos/network/network_siminfo.js | 480 +----- .../cr_components/chromeos/network/onc_mojo.js | 54 +- .../chromeos/network/sim_lock_dialogs.html | 155 ++ .../chromeos/network/sim_lock_dialogs.js | 537 +++++++ .../network_health/network_health_container.js | 5 +- .../network_health/network_health_summary.html | 4 +- .../network_health/network_health_summary.js | 32 + .../chromeos/network_health/routine_group.html | 5 +- .../chromeos/network_health/routine_group.js | 9 + .../cr_components/chromeos/os_cr_components.gni | 4 +- .../chromeos/quick_unlock/pin_keyboard.html | 6 +- .../chromeos/quick_unlock/setup_pin_keyboard.html | 13 +- .../chromeos/smb_shares/add_smb_share_dialog.html | 2 +- .../chromeos/smb_shares/add_smb_share_dialog.js | 36 +- .../chromeos/smb_shares/smb_browser_proxy.js | 1 + .../cr_components/customize_themes/BUILD.gn | 1 + .../customize_themes/customize_themes.html | 8 +- .../customize_themes/customize_themes.js | 41 +- .../customize_themes/customize_themes.mojom | 2 + .../cr_components/managed_dialog/BUILD.gn | 23 + .../managed_dialog/managed_dialog.html | 26 + .../cr_components/managed_dialog/managed_dialog.js | 38 + chromium/ui/webui/resources/cr_elements/BUILD.gn | 107 +- .../cr_elements/cr_action_menu/cr_action_menu.js | 4 - .../cr_elements/cr_actionable_row_style.html | 38 + .../resources/cr_elements/cr_dialog/cr_dialog.js | 4 - .../webui/resources/cr_elements/cr_drawer/BUILD.gn | 32 +- .../resources/cr_elements/cr_drawer/cr_drawer.html | 12 - .../resources/cr_elements/cr_drawer/cr_drawer.js | 15 +- .../cr_expand_button/cr_expand_button.html | 10 +- .../cr_elements/cr_icon_button/cr_icon_button.html | 29 +- .../cr_elements/cr_icon_button/cr_icon_button.js | 67 - .../cr_elements/cr_input/cr_input_style_css.html | 1 + .../resources/cr_elements/cr_link_row/BUILD.gn | 19 +- .../cr_elements/cr_link_row/cr_link_row.html | 150 +- .../cr_elements/cr_link_row/cr_link_row.js | 13 +- .../cr_elements/cr_page_host_style_css.html | 26 +- .../cr_elements/cr_page_host_style_css.js | 12 + .../resources/cr_elements/cr_search_field/BUILD.gn | 58 +- .../cr_search_field/cr_search_field.html | 24 +- .../cr_elements/cr_search_field/cr_search_field.js | 13 + .../cr_search_field/cr_search_field_behavior.html | 1 - .../cr_search_field/cr_search_field_behavior.js | 5 +- .../resources/cr_elements/cr_slider/cr_slider.js | 12 +- .../cr_elements/cr_splitter/cr_splitter.js | 131 +- .../webui/resources/cr_elements/cr_tabs/BUILD.gn | 23 +- .../resources/cr_elements/cr_tabs/cr_tabs.html | 10 - .../webui/resources/cr_elements/cr_tabs/cr_tabs.js | 8 +- .../resources/cr_elements/cr_toolbar/BUILD.gn | 52 +- .../cr_elements/cr_toolbar/cr_toolbar.html | 1 + .../resources/cr_elements/cr_toolbar/cr_toolbar.js | 6 +- .../cr_toolbar/cr_toolbar_search_field.html | 18 +- .../cr_toolbar/cr_toolbar_search_field.js | 13 + .../resources/cr_elements/cr_view_manager/BUILD.gn | 24 +- .../cr_view_manager/cr_view_manager.html | 9 - .../cr_elements/cr_view_manager/cr_view_manager.js | 9 +- .../cr_elements/find_shortcut_behavior.js | 17 +- chromium/ui/webui/resources/cr_elements/icons.html | 5 + .../resources/cr_elements/mwb_shared_vars.html | 2 + .../cr_elements/policy/cr_tooltip_icon.html | 3 +- .../cr_elements/search_highlight_style_css.html | 6 - .../cr_elements/search_highlight_style_css.js | 12 + .../resources/cr_elements/shared_style_css.html | 1 + .../resources/cr_elements/shared_vars_css.html | 8 + chromium/ui/webui/resources/images/BUILD.gn | 17 +- chromium/ui/webui/resources/images/error_badge.svg | 1 - .../ui/webui/resources/images/icon_bookmark.svg | 1 + .../ui/webui/resources/images/icon_bookmarks.svg | 1 - chromium/ui/webui/resources/js/BUILD.gn | 8 +- chromium/ui/webui/resources/js/cr.gni | 1 - chromium/ui/webui/resources/js/cr/ui/BUILD.gn | 59 +- chromium/ui/webui/resources/js/cr/ui/dialogs.js | 60 - chromium/ui/webui/resources/js/cr/ui/splitter.js | 33 - chromium/ui/webui/resources/js/cr/world.ts | 9 + chromium/ui/webui/resources/js/custom_element.js | 35 + chromium/ui/webui/resources/js/hello_world.ts | 11 + chromium/ui/webui/resources/js/icon.js | 8 +- chromium/ui/webui/resources/js/load_time_data.js | 356 ++-- chromium/ui/webui/resources/tools/js_modulizer.py | 28 +- .../ui/webui/resources/tools/js_modulizer_test.py | 10 +- chromium/ui/webui/resources/webui_resources.grd | 9 - chromium/ui/wm/core/cursor_manager.cc | 3 +- chromium/ui/wm/core/native_cursor_manager.h | 3 +- chromium/ui/wm/public/DEPS | 9 - chromium/ui/wm/public/tooltip_client.cc | 10 +- chromium/ui/wm/public/tooltip_client.h | 21 +- 1403 files changed, 31371 insertions(+), 22561 deletions(-) create mode 100644 chromium/ui/accessibility/ax_action_handler_registry.cc create mode 100644 chromium/ui/accessibility/ax_action_handler_registry.h delete mode 100644 chromium/ui/accessibility/ax_event_bundle_sink.h delete mode 100644 chromium/ui/accessibility/ax_tree_id_registry.cc delete mode 100644 chromium/ui/accessibility/ax_tree_id_registry.h create mode 100644 chromium/ui/accessibility/ax_tree_id_unittest.cc create mode 100644 chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc create mode 100644 chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.h create mode 100644 chromium/ui/android/junit/src/org/chromium/ui/widget/LoadingViewTest.java delete mode 100644 chromium/ui/base/accelerators/accelerator_history.cc delete mode 100644 chromium/ui/base/accelerators/accelerator_history.h delete mode 100644 chromium/ui/base/accelerators/accelerator_history_unittest.cc create mode 100644 chromium/ui/base/clipboard/clipboard_factory_ozone.cc delete mode 100644 chromium/ui/base/clipboard/clipboard_linux.cc create mode 100644 chromium/ui/base/dragdrop/BUILD.gn create mode 100644 chromium/ui/base/glib/OWNERS create mode 100644 chromium/ui/base/glib/glib_cast.h create mode 100644 chromium/ui/base/idle/idle_lacros.cc create mode 100644 chromium/ui/base/ime/fuchsia/OWNERS create mode 100644 chromium/ui/base/ime/fuchsia/keyboard_client.cc create mode 100644 chromium/ui/base/ime/fuchsia/keyboard_client.h create mode 100644 chromium/ui/base/linux/OWNERS create mode 100644 chromium/ui/base/linux/linux_desktop.cc create mode 100644 chromium/ui/base/linux/linux_desktop.h create mode 100644 chromium/ui/base/x/x11_clipboard_helper.cc create mode 100644 chromium/ui/base/x/x11_clipboard_helper.h create mode 100644 chromium/ui/base/x/x11_global_shortcut_listener.cc create mode 100644 chromium/ui/base/x/x11_global_shortcut_listener.h delete mode 100644 chromium/ui/base/x/x11_window.cc delete mode 100644 chromium/ui/base/x/x11_window.h create mode 100644 chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.cc create mode 100644 chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.h create mode 100644 chromium/ui/color/color_provider_utils.cc create mode 100644 chromium/ui/color/color_provider_utils.h create mode 100644 chromium/ui/color/ios/native_color_mixers.mm create mode 100644 chromium/ui/color/mac/native_color_transform.mm create mode 100644 chromium/ui/color/mac/system_color_utils.h create mode 100644 chromium/ui/color/mac/system_color_utils.mm delete mode 100644 chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h create mode 100644 chromium/ui/events/fuchsia/input_event_sink.h delete mode 100644 chromium/ui/file_manager/externs/BUILD.gn delete mode 100644 chromium/ui/file_manager/externs/background/BUILD.gn create mode 100644 chromium/ui/file_manager/file_manager/externs/BUILD.gn create mode 100644 chromium/ui/file_manager/file_manager/externs/background/BUILD.gn delete mode 100644 chromium/ui/file_manager/file_manager/test/BUILD.gn delete mode 100644 chromium/ui/file_manager/file_manager/test/js/BUILD.gn create mode 100644 chromium/ui/gfx/animation/keyframe/keyframed_animation_curve-inl.h create mode 100644 chromium/ui/gfx/delegated_ink_metadata.cc create mode 100644 chromium/ui/gfx/delegated_ink_metadata.h create mode 100644 chromium/ui/gfx/delegated_ink_point.cc create mode 100644 chromium/ui/gfx/delegated_ink_point.h create mode 100644 chromium/ui/gfx/mojom/delegated_ink_metadata.mojom create mode 100644 chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.cc create mode 100644 chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.h create mode 100644 chromium/ui/gfx/mojom/delegated_ink_point.mojom create mode 100644 chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.cc create mode 100644 chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.h create mode 100644 chromium/ui/gl/delegated_ink_point_renderer_gpu.h create mode 100644 chromium/ui/gtk/gdk.sigs delete mode 100644 chromium/ui/gtk/gdk_pixbuf.fragment create mode 100644 chromium/ui/gtk/gio.sigs create mode 100644 chromium/ui/gtk/gsk.sigs create mode 100644 chromium/ui/gtk/gtk.fragment create mode 100644 chromium/ui/gtk/gtk.sigs create mode 100644 chromium/ui/gtk/gtk_color_mixers.cc create mode 100644 chromium/ui/gtk/gtk_color_mixers.h create mode 100644 chromium/ui/gtk/gtk_compat.cc create mode 100644 chromium/ui/gtk/gtk_compat.h create mode 100644 chromium/ui/gtk/gtk_types.h create mode 100644 chromium/ui/gtk/log_noop.h create mode 100644 chromium/ui/gtk/native_theme_gtk_unittest.cc create mode 100644 chromium/ui/gtk/wayland/BUILD.gn create mode 100644 chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc create mode 100644 chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.h delete mode 100644 chromium/ui/login/BUILD.gn delete mode 100644 chromium/ui/login/DIR_METADATA delete mode 100644 chromium/ui/login/OWNERS delete mode 100644 chromium/ui/login/bubble.css delete mode 100644 chromium/ui/login/bubble.js delete mode 100644 chromium/ui/login/display_manager.js delete mode 100644 chromium/ui/login/display_manager_types.js delete mode 100644 chromium/ui/login/login_ui_tools.js delete mode 100644 chromium/ui/login/oobe.css delete mode 100644 chromium/ui/login/screen.js delete mode 100644 chromium/ui/login/screen_container.css create mode 100644 chromium/ui/native_theme/native_theme_utils.cc create mode 100644 chromium/ui/native_theme/native_theme_utils.h create mode 100644 chromium/ui/ozone/platform/scenic/safe_presenter.cc create mode 100644 chromium/ui/ozone/platform/scenic/safe_presenter.h create mode 100644 chromium/ui/ozone/platform/scenic/scenic_window_unittest.cc create mode 100644 chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc create mode 100644 chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h create mode 100644 chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.cc create mode 100644 chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h create mode 100644 chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc create mode 100644 chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.h create mode 100644 chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.cc create mode 100644 chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.h create mode 100644 chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.cc create mode 100644 chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h create mode 100644 chromium/ui/ozone/platform/x11/x11_utils.cc create mode 100644 chromium/ui/ozone/platform/x11/x11_utils.h create mode 100644 chromium/ui/ozone/public/platform_global_shortcut_listener.cc create mode 100644 chromium/ui/ozone/public/platform_global_shortcut_listener.h create mode 100644 chromium/ui/ozone/public/platform_utils.h create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block_big.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block_big.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block_big.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block.png create mode 100644 chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block_big.png create mode 100644 chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow_block.png create mode 100644 chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow_block.png create mode 100644 chromium/ui/resources/default_200_percent/common/pointers/top_left_corner_block.png create mode 100644 chromium/ui/resources/default_200_percent/common/pointers/top_right_corner_block.png create mode 100644 chromium/ui/views/corewm/tooltip_state_manager.cc create mode 100644 chromium/ui/views/corewm/tooltip_state_manager.h create mode 100644 chromium/ui/views/examples/notification_example.cc create mode 100644 chromium/ui/views/examples/notification_example.h create mode 100644 chromium/ui/views/image_model_utils.cc create mode 100644 chromium/ui/views/image_model_utils.h create mode 100644 chromium/ui/views/image_model_utils_unittest.cc delete mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_1x.png delete mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_2x.png delete mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_1x.png delete mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_2x.png delete mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_selection_flow.html delete mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/setup_selection_flow.js create mode 100644 chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/sim_detect_error.svg create mode 100644 chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html create mode 100644 chromium/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js create mode 100644 chromium/ui/webui/resources/cr_components/managed_dialog/BUILD.gn create mode 100644 chromium/ui/webui/resources/cr_components/managed_dialog/managed_dialog.html create mode 100644 chromium/ui/webui/resources/cr_components/managed_dialog/managed_dialog.js create mode 100644 chromium/ui/webui/resources/cr_elements/cr_actionable_row_style.html create mode 100644 chromium/ui/webui/resources/cr_elements/cr_page_host_style_css.js delete mode 100644 chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.html create mode 100644 chromium/ui/webui/resources/cr_elements/search_highlight_style_css.js delete mode 100644 chromium/ui/webui/resources/images/error_badge.svg create mode 100644 chromium/ui/webui/resources/images/icon_bookmark.svg delete mode 100644 chromium/ui/webui/resources/images/icon_bookmarks.svg create mode 100644 chromium/ui/webui/resources/js/cr/world.ts create mode 100644 chromium/ui/webui/resources/js/custom_element.js create mode 100644 chromium/ui/webui/resources/js/hello_world.ts delete mode 100644 chromium/ui/wm/public/DEPS (limited to 'chromium/ui') diff --git a/chromium/ui/accelerated_widget_mac/ca_transaction_observer.h b/chromium/ui/accelerated_widget_mac/ca_transaction_observer.h index eb8618095b8..3155897c49b 100644 --- a/chromium/ui/accelerated_widget_mac/ca_transaction_observer.h +++ b/chromium/ui/accelerated_widget_mac/ca_transaction_observer.h @@ -5,6 +5,8 @@ #ifndef UI_ACCELERATED_WIDGET_MAC_CA_TRANSACTION_OBSERVER_H_ #define UI_ACCELERATED_WIDGET_MAC_CA_TRANSACTION_OBSERVER_H_ +#include + #include "base/callback.h" #include "base/macros.h" #include "base/observer_list.h" diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn index 3e693fd9e01..b4707c34628 100644 --- a/chromium/ui/accessibility/BUILD.gn +++ b/chromium/ui/accessibility/BUILD.gn @@ -48,6 +48,8 @@ component("ax_base") { "ax_action_handler.h", "ax_action_handler_base.cc", "ax_action_handler_base.h", + "ax_action_handler_registry.cc", + "ax_action_handler_registry.h", "ax_base_export.h", "ax_enum_util.cc", "ax_enum_util.h", @@ -69,8 +71,6 @@ component("ax_base") { "ax_tree_data.h", "ax_tree_id.cc", "ax_tree_id.h", - "ax_tree_id_registry.cc", - "ax_tree_id_registry.h", "ax_tree_update.cc", "ax_tree_update.h", "ax_tree_update_forward.h", @@ -108,7 +108,6 @@ component("accessibility") { "ax_active_popup.h", "ax_clipping_behavior.h", "ax_coordinate_system.h", - "ax_event_bundle_sink.h", "ax_event_generator.cc", "ax_event_generator.h", "ax_export.h", @@ -227,6 +226,7 @@ test("accessibility_unittests") { "ax_table_info_unittest.cc", "ax_text_utils_unittest.cc", "ax_tree_combiner_unittest.cc", + "ax_tree_id_unittest.cc", "ax_tree_serializer_unittest.cc", "ax_tree_source_checker_unittest.cc", "ax_tree_unittest.cc", diff --git a/chromium/ui/accessibility/PRESUBMIT.py b/chromium/ui/accessibility/PRESUBMIT.py index 0cbcf9bd9e6..c97381a70c1 100644 --- a/chromium/ui/accessibility/PRESUBMIT.py +++ b/chromium/ui/accessibility/PRESUBMIT.py @@ -159,6 +159,10 @@ def CheckEnumsMatch(input_api, output_api): 'IntentMoveDirectionType', errs, output_api) CheckMatchingEnum(ax_enums, 'SortDirection', automation_enums, 'SortDirectionType', errs, output_api) + CheckMatchingEnum(ax_enums, 'HasPopup', automation_enums, + 'HasPopup', errs, output_api) + CheckMatchingEnum(ax_enums, 'AriaCurrentState', automation_enums, + 'AriaCurrentState', errs, output_api) return errs # Given a full path to c++ header, return an array of the first static diff --git a/chromium/ui/accessibility/accessibility_features.cc b/chromium/ui/accessibility/accessibility_features.cc index 04a19ee4f94..07cd30ebfe1 100644 --- a/chromium/ui/accessibility/accessibility_features.cc +++ b/chromium/ui/accessibility/accessibility_features.cc @@ -77,6 +77,13 @@ bool IsAccessibilityFocusHighlightEnabled() { return base::FeatureList::IsEnabled(::features::kAccessibilityFocusHighlight); } +const base::Feature kAutoDisableAccessibility{ + "AutoDisableAccessibility", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsAutoDisableAccessibilityEnabled() { + return base::FeatureList::IsEnabled(::features::kAutoDisableAccessibility); +} + #if defined(OS_WIN) const base::Feature kIChromeAccessible{"IChromeAccessible", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -110,6 +117,14 @@ bool IsMagnifierContinuousMouseFollowingModeSettingEnabled() { return base::FeatureList::IsEnabled( ::features::kMagnifierContinuousMouseFollowingModeSetting); } + +const base::Feature kEnableSwitchAccessPointScanning{ + "EnableSwitchAccessPointScanning", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsSwitchAccessPointScanningEnabled() { + return base::FeatureList::IsEnabled( + ::features::kEnableSwitchAccessPointScanning); +} #endif // BUILDFLAG(IS_CHROMEOS_ASH) const base::Feature kAugmentExistingImageLabels{ diff --git a/chromium/ui/accessibility/accessibility_features.h b/chromium/ui/accessibility/accessibility_features.h index 0fd6eca4895..848656cc4af 100644 --- a/chromium/ui/accessibility/accessibility_features.h +++ b/chromium/ui/accessibility/accessibility_features.h @@ -61,6 +61,13 @@ AX_BASE_EXPORT extern const base::Feature kAccessibilityFocusHighlight; // briefly whenever focus changes. AX_BASE_EXPORT bool IsAccessibilityFocusHighlightEnabled(); +AX_BASE_EXPORT extern const base::Feature kAutoDisableAccessibility; + +// Returns true if accessibility will be auto-disabled after a certain +// number of user input events spanning a minimum amount of time with no +// accessibility API usage in that time. +AX_BASE_EXPORT bool IsAutoDisableAccessibilityEnabled(); + #if defined(OS_WIN) // Enables an experimental Chrome-specific accessibility COM API AX_BASE_EXPORT extern const base::Feature kIChromeAccessible; @@ -93,6 +100,13 @@ AX_BASE_EXPORT extern const base::Feature // Returns true if the feature to allow choosing the new continuous mouse // following mode in Magnifier settings is enabled. AX_BASE_EXPORT bool IsMagnifierContinuousMouseFollowingModeSettingEnabled(); + +// Enables ability to choose point scanning mode in switch access. +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(); #endif // BUILDFLAG(IS_CHROMEOS_ASH) // Enables Get Image Descriptions to augment existing images labels, diff --git a/chromium/ui/accessibility/accessibility_switches.cc b/chromium/ui/accessibility/accessibility_switches.cc index be3f94f7ce9..3bd01485bb3 100644 --- a/chromium/ui/accessibility/accessibility_switches.cc +++ b/chromium/ui/accessibility/accessibility_switches.cc @@ -18,9 +18,16 @@ const char kEnableExperimentalAccessibilityAutoclick[] = const char kEnableExperimentalAccessibilityDictationExtension[] = "enable-experimental-accessibility-dictation-extension"; +// Enables dictation to use on-device speech recognition. 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[] = @@ -40,9 +47,9 @@ const char kEnableExperimentalAccessibilityLanguageDetectionDynamic[] = const char kEnableExperimentalAccessibilitySwitchAccessText[] = "enable-experimental-accessibility-switch-access-text"; -// Enables Switch Access point scanning. This feature hasn't launched yet. -const char kEnableSwitchAccessPointScanning[] = - "enable-switch-access-point-scanning"; +// Enables debug feature for drawing rectangle around magnified region, without +// zooming in. +const char kEnableMagnifierDebugDrawRect[] = "enable-magnifier-debug-draw-rect"; // Enables the Switch Access setup guide that hasn't launched yet. const char kEnableExperimentalAccessibilitySwitchAccessSetupGuide[] = @@ -58,6 +65,11 @@ bool IsExperimentalAccessibilityDictationOfflineEnabled() { ::switches::kEnableExperimentalAccessibilityDictationOffline); } +bool IsExperimentalAccessibilityDictationListeningEnabled() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kEnableExperimentalAccessibilityDictationListening); +} + bool IsExperimentalAccessibilityLanguageDetectionEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kEnableExperimentalAccessibilityLanguageDetection); @@ -73,9 +85,9 @@ bool IsExperimentalAccessibilitySwitchAccessTextEnabled() { ::switches::kEnableExperimentalAccessibilitySwitchAccessText); } -bool IsSwitchAccessPointScanningEnabled() { +bool IsMagnifierDebugDrawRectEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kEnableSwitchAccessPointScanning); + ::switches::kEnableMagnifierDebugDrawRect); } #if defined(OS_WIN) diff --git a/chromium/ui/accessibility/accessibility_switches.h b/chromium/ui/accessibility/accessibility_switches.h index 6a5280cb817..5dfeba83b64 100644 --- a/chromium/ui/accessibility/accessibility_switches.h +++ b/chromium/ui/accessibility/accessibility_switches.h @@ -16,6 +16,8 @@ AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityDictationExtension[]; AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityDictationOffline[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilityDictationListening[]; AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityLabelsDebugging[]; AX_BASE_EXPORT extern const char @@ -24,7 +26,6 @@ AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityLanguageDetectionDynamic[]; AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccessText[]; -AX_BASE_EXPORT extern const char kEnableSwitchAccessPointScanning[]; AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccessSetupGuide[]; @@ -34,6 +35,10 @@ 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(); @@ -53,7 +58,7 @@ AX_BASE_EXPORT extern const char kEnableExperimentalUIAutomation[]; AX_BASE_EXPORT bool IsExperimentalAccessibilityPlatformUIAEnabled(); // Returns true if Switch Access point scanning is enabled. -AX_BASE_EXPORT bool IsSwitchAccessPointScanningEnabled(); +AX_BASE_EXPORT bool IsMagnifierDebugDrawRectEnabled(); // Optionally disable AXMenuList, which makes the internal pop-up menu // UI for a select element directly accessible. diff --git a/chromium/ui/accessibility/ax_action_handler.cc b/chromium/ui/accessibility/ax_action_handler.cc index 3ac9ce81c3f..6affa11ab6f 100644 --- a/chromium/ui/accessibility/ax_action_handler.cc +++ b/chromium/ui/accessibility/ax_action_handler.cc @@ -4,12 +4,12 @@ #include "ui/accessibility/ax_action_handler.h" -#include "ui/accessibility/ax_tree_id_registry.h" +#include "ui/accessibility/ax_action_handler_registry.h" namespace ui { AXActionHandler::AXActionHandler() : AXActionHandlerBase( - AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(this)) {} + AXActionHandlerRegistry::GetInstance()->GetOrCreateAXTreeID(this)) {} } // namespace ui diff --git a/chromium/ui/accessibility/ax_action_handler.h b/chromium/ui/accessibility/ax_action_handler.h index 0b7cdf6861a..03d3c033b49 100644 --- a/chromium/ui/accessibility/ax_action_handler.h +++ b/chromium/ui/accessibility/ax_action_handler.h @@ -12,7 +12,8 @@ namespace ui { // The class you normally want to inherit from other classes when you want to // make them visible to accessibility clients, since it automatically registers -// a valid AXTreeID with the AXTreeIDRegistry when constructing the instance. +// a valid AXTreeID with the AXActionHandlerRegistry when constructing the +// instance. // // If you need more control over how the AXTreeID associated to this class is // set, please inherit directly from AXActionHandlerBase instead. diff --git a/chromium/ui/accessibility/ax_action_handler_base.cc b/chromium/ui/accessibility/ax_action_handler_base.cc index 43edc1e21e7..58e571d377e 100644 --- a/chromium/ui/accessibility/ax_action_handler_base.cc +++ b/chromium/ui/accessibility/ax_action_handler_base.cc @@ -4,7 +4,7 @@ #include "ui/accessibility/ax_action_handler_base.h" -#include "ui/accessibility/ax_tree_id_registry.h" +#include "ui/accessibility/ax_action_handler_registry.h" namespace ui { @@ -19,14 +19,14 @@ AXActionHandlerBase::AXActionHandlerBase(const AXTreeID& ax_tree_id) : tree_id_(ax_tree_id) {} AXActionHandlerBase::~AXActionHandlerBase() { - AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(tree_id_); + AXActionHandlerRegistry::GetInstance()->RemoveAXTreeID(tree_id_); } void AXActionHandlerBase::SetAXTreeID(AXTreeID new_ax_tree_id) { DCHECK_NE(new_ax_tree_id, ui::AXTreeIDUnknown()); - AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(tree_id_); + AXActionHandlerRegistry::GetInstance()->RemoveAXTreeID(tree_id_); tree_id_ = new_ax_tree_id; - AXTreeIDRegistry::GetInstance()->SetAXTreeID(tree_id_, this); + AXActionHandlerRegistry::GetInstance()->SetAXTreeID(tree_id_, this); } } // namespace ui diff --git a/chromium/ui/accessibility/ax_action_handler_base.h b/chromium/ui/accessibility/ax_action_handler_base.h index ee2522edad2..93ce3a23f0e 100644 --- a/chromium/ui/accessibility/ax_action_handler_base.h +++ b/chromium/ui/accessibility/ax_action_handler_base.h @@ -47,7 +47,7 @@ class AX_BASE_EXPORT AXActionHandlerBase { void SetAXTreeID(AXTreeID new_ax_tree_id); private: - // Register or unregister this class with |AXTreeIDRegistry|. + // Register or unregister this class with |AXActionHandlerRegistry|. void UpdateActiveState(bool active); // Manually set in this base class, but automatically set by instances of the diff --git a/chromium/ui/accessibility/ax_action_handler_registry.cc b/chromium/ui/accessibility/ax_action_handler_registry.cc new file mode 100644 index 00000000000..43a3806b874 --- /dev/null +++ b/chromium/ui/accessibility/ax_action_handler_registry.cc @@ -0,0 +1,111 @@ +// 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/accessibility/ax_action_handler_registry.h" + +#include "base/memory/singleton.h" +#include "base/strings/string_number_conversions.h" +#include "ui/accessibility/ax_action_handler_base.h" + +namespace ui { + +// static +AXActionHandlerRegistry* AXActionHandlerRegistry::GetInstance() { + return base::Singleton::get(); +} + +void AXActionHandlerRegistry::SetFrameIDForAXTreeID( + const FrameID& frame_id, + const AXTreeID& ax_tree_id) { + auto it = frame_to_ax_tree_id_map_.find(frame_id); + if (it != frame_to_ax_tree_id_map_.end()) { + NOTREACHED(); + return; + } + + frame_to_ax_tree_id_map_[frame_id] = ax_tree_id; + ax_tree_to_frame_id_map_[ax_tree_id] = frame_id; +} + +void AXActionHandlerRegistry::AddObserver(AXActionHandlerObserver* observer) { + observers_.AddObserver(observer); +} + +void AXActionHandlerRegistry::RemoveObserver( + AXActionHandlerObserver* observer) { + observers_.RemoveObserver(observer); +} + +void AXActionHandlerRegistry::PerformAction( + const ui::AXTreeID& tree_id, + int32_t automation_node_id, + const std::string& action_type, + int32_t request_id, + const base::DictionaryValue& optional_args) { + for (AXActionHandlerObserver& observer : observers_) { + observer.PerformAction(tree_id, automation_node_id, action_type, request_id, + optional_args); + } +} + +AXActionHandlerRegistry::FrameID AXActionHandlerRegistry::GetFrameID( + const AXTreeID& ax_tree_id) { + auto it = ax_tree_to_frame_id_map_.find(ax_tree_id); + if (it != ax_tree_to_frame_id_map_.end()) + return it->second; + + return FrameID(-1, -1); +} + +AXTreeID AXActionHandlerRegistry::GetAXTreeID( + AXActionHandlerRegistry::FrameID frame_id) { + auto it = frame_to_ax_tree_id_map_.find(frame_id); + if (it != frame_to_ax_tree_id_map_.end()) + return it->second; + + return ui::AXTreeIDUnknown(); +} + +AXTreeID AXActionHandlerRegistry::GetOrCreateAXTreeID( + AXActionHandlerBase* handler) { + for (auto it : id_to_action_handler_) { + if (it.second == handler) + return it.first; + } + AXTreeID new_id = AXTreeID::CreateNewAXTreeID(); + SetAXTreeID(new_id, handler); + return new_id; +} + +AXActionHandlerBase* AXActionHandlerRegistry::GetActionHandler( + AXTreeID ax_tree_id) { + auto it = id_to_action_handler_.find(ax_tree_id); + if (it == id_to_action_handler_.end()) + return nullptr; + return it->second; +} + +void AXActionHandlerRegistry::SetAXTreeID(const ui::AXTreeID& id, + AXActionHandlerBase* action_handler) { + DCHECK(id_to_action_handler_.find(id) == id_to_action_handler_.end()); + id_to_action_handler_[id] = action_handler; +} + +void AXActionHandlerRegistry::RemoveAXTreeID(AXTreeID ax_tree_id) { + auto frame_it = ax_tree_to_frame_id_map_.find(ax_tree_id); + if (frame_it != ax_tree_to_frame_id_map_.end()) { + frame_to_ax_tree_id_map_.erase(frame_it->second); + ax_tree_to_frame_id_map_.erase(frame_it); + } + + auto action_it = id_to_action_handler_.find(ax_tree_id); + if (action_it != id_to_action_handler_.end()) + id_to_action_handler_.erase(action_it); +} + +AXActionHandlerRegistry::AXActionHandlerRegistry() {} + +AXActionHandlerRegistry::~AXActionHandlerRegistry() {} + +} // namespace ui diff --git a/chromium/ui/accessibility/ax_action_handler_registry.h b/chromium/ui/accessibility/ax_action_handler_registry.h new file mode 100644 index 00000000000..da101c7c3db --- /dev/null +++ b/chromium/ui/accessibility/ax_action_handler_registry.h @@ -0,0 +1,117 @@ +// 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. + +#ifndef UI_ACCESSIBILITY_AX_ACTION_HANDLER_REGISTRY_H_ +#define UI_ACCESSIBILITY_AX_ACTION_HANDLER_REGISTRY_H_ + +#include +#include +#include +#include + +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "ui/accessibility/ax_action_handler.h" +#include "ui/accessibility/ax_base_export.h" +#include "ui/accessibility/ax_tree_id.h" + +namespace base { +template +struct DefaultSingletonTraits; +} // namespace base + +namespace ui { + +class AXActionHandlerBase; + +// An observer is informed of all automation actions. +class AXActionHandlerObserver : public base::CheckedObserver { + public: + // This method is intended to route actions to their final destinations. The + // routing is asynchronous and we do not know which observers intend to + // respond to which actions -- so we forward all actions to all observers. + // Only the observer that owns the unique |tree_id| will perform the action. + virtual void PerformAction(const ui::AXTreeID& tree_id, + int32_t automation_node_id, + const std::string& action_type, + int32_t request_id, + const base::DictionaryValue& optional_args) = 0; +}; + +// This class generates and saves a runtime id for an accessibility tree. +// It provides a few distinct forms of generating an id: +// - from a frame id (which consists of a process and routing id) +// - from a backing |AXActionHandlerBase| object +// +// The first form allows underlying instances to change but refer to the same +// frame. +// The second form allows this registry to track the object for later retrieval. +class AX_BASE_EXPORT AXActionHandlerRegistry { + public: + using FrameID = std::pair; + + // Get the single instance of this class. + static AXActionHandlerRegistry* GetInstance(); + + // Gets the frame id based on an ax tree id. + FrameID GetFrameID(const AXTreeID& ax_tree_id); + + // Gets an ax tree id from a frame id. + AXTreeID GetAXTreeID(FrameID frame_id); + + // Retrieve an |AXActionHandlerBase| based on an ax tree id. + AXActionHandlerBase* GetActionHandler(AXTreeID ax_tree_id); + + // Removes an ax tree id, and its associated delegate and frame id (if it + // exists). + void RemoveAXTreeID(AXTreeID ax_tree_id); + + // Associate a frame id with an ax tree id. + void SetFrameIDForAXTreeID(const FrameID& frame_id, + const AXTreeID& ax_tree_id); + + void AddObserver(AXActionHandlerObserver* observer); + void RemoveObserver(AXActionHandlerObserver* observer); + + // Calls PerformAction on all observers. + void PerformAction(const ui::AXTreeID& tree_id, + int32_t automation_node_id, + const std::string& action_type, + int32_t request_id, + const base::DictionaryValue& optional_args); + + private: + friend struct base::DefaultSingletonTraits; + friend AXActionHandler; + friend AXActionHandlerBase; + + // Get or create a ax tree id keyed on |handler|. + AXTreeID GetOrCreateAXTreeID(AXActionHandlerBase* handler); + + // Set a mapping between an AXTreeID and AXActionHandlerBase explicitly. + void SetAXTreeID(const AXTreeID& ax_tree_id, + AXActionHandlerBase* action_handler); + + AXActionHandlerRegistry(); + virtual ~AXActionHandlerRegistry(); + + // Maps an accessibility tree to its frame via ids. + std::map ax_tree_to_frame_id_map_; + + // Maps frames to an accessibility tree via ids. + std::map frame_to_ax_tree_id_map_; + + // Maps an id to its handler. + std::map id_to_action_handler_; + + // Tracks all observers. + base::ObserverList observers_; + + DISALLOW_COPY_AND_ASSIGN(AXActionHandlerRegistry); +}; + +} // namespace ui + +#endif // UI_ACCESSIBILITY_AX_ACTION_HANDLER_REGISTRY_H_ diff --git a/chromium/ui/accessibility/ax_assistant_structure.cc b/chromium/ui/accessibility/ax_assistant_structure.cc index 127063bbf69..ffc101c9509 100644 --- a/chromium/ui/accessibility/ax_assistant_structure.cc +++ b/chromium/ui/accessibility/ax_assistant_structure.cc @@ -90,11 +90,11 @@ bool IsLeaf(const AXNode* node) { } } -base::string16 GetInnerText(const AXNode* node) { +std::u16string GetInnerText(const AXNode* node) { if (node->IsText()) { return node->data().GetString16Attribute(ax::mojom::StringAttribute::kName); } - base::string16 text; + std::u16string text; for (size_t i = 0; i < node->GetUnignoredChildCount(); ++i) { AXNode* child = node->GetUnignoredChildAtIndex(i); text += GetInnerText(child); @@ -102,8 +102,8 @@ base::string16 GetInnerText(const AXNode* node) { return text; } -base::string16 GetValue(const AXNode* node) { - base::string16 value = +std::u16string GetValue(const AXNode* node) { + std::u16string value = node->data().GetString16Attribute(ax::mojom::StringAttribute::kValue); if (value.empty() && @@ -115,25 +115,25 @@ base::string16 GetValue(const AXNode* node) { // Always obscure passwords. if (node->data().HasState(ax::mojom::State::kProtected)) - value = base::string16(value.size(), kSecurePasswordBullet); + value = std::u16string(value.size(), kSecurePasswordBullet); return value; } -base::string16 GetText(const AXNode* node) { +std::u16string GetText(const AXNode* node) { if (node->data().role == ax::mojom::Role::kPdfRoot || node->data().role == ax::mojom::Role::kIframe || node->data().role == ax::mojom::Role::kIframePresentational) { - return base::string16(); + return std::u16string(); } ax::mojom::NameFrom name_from = node->data().GetNameFrom(); if (!ui::IsLeaf(node) && name_from == ax::mojom::NameFrom::kContents) { - return base::string16(); + return std::u16string(); } - base::string16 value = GetValue(node); + std::u16string value = GetValue(node); if (!value.empty()) { if (node->data().HasState(ax::mojom::State::kEditable)) @@ -160,13 +160,13 @@ base::string16 GetText(const AXNode* node) { base::StringPrintf("#%02X%02X%02X", red, green, blue)); } - base::string16 text = + std::u16string text = node->data().GetString16Attribute(ax::mojom::StringAttribute::kName); - base::string16 description = node->data().GetString16Attribute( + std::u16string description = node->data().GetString16Attribute( ax::mojom::StringAttribute::kDescription); if (!description.empty()) { if (!text.empty()) - text += base::ASCIIToUTF16(" "); + text += u" "; text += description; } @@ -187,7 +187,7 @@ base::string16 GetText(const AXNode* node) { if (text.empty() && (ui::IsLink(node->data().role) || node->data().role == ax::mojom::Role::kImage)) { - base::string16 url = + std::u16string url = node->data().GetString16Attribute(ax::mojom::StringAttribute::kUrl); text = AXUrlBaseText(url); } @@ -323,6 +323,11 @@ void WalkAXTreeDepthFirst(const AXNode* node, 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); for (size_t i = 0; i < node->GetUnignoredChildCount(); ++i) { AXNode* child = node->GetUnignoredChildAtIndex(i); @@ -361,7 +366,7 @@ std::unique_ptr CreateAssistantTree(const AXTreeUpdate& update) { return assistant_tree; } -base::string16 AXUrlBaseText(base::string16 url) { +std::u16string AXUrlBaseText(std::u16string url) { // Given a url like http://foo.com/bar/baz.png, just return the // base text, e.g., "baz". int trailing_slashes = 0; diff --git a/chromium/ui/accessibility/ax_assistant_structure.h b/chromium/ui/accessibility/ax_assistant_structure.h index 4e8358a7072..c9003cfd36f 100644 --- a/chromium/ui/accessibility/ax_assistant_structure.h +++ b/chromium/ui/accessibility/ax_assistant_structure.h @@ -13,7 +13,6 @@ #include "base/macros.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/accessibility/ax_export.h" #include "ui/accessibility/ax_tree_update.h" @@ -34,7 +33,7 @@ struct AssistantNode { gfx::Rect rect; // Text of the view. - base::string16 text; + std::u16string text; // Text properties float text_size; @@ -52,8 +51,11 @@ struct AssistantNode { // a closest approximation of Android's views to keep the server happy. std::string class_name; - // HTML tag name + // HTML and CSS attributes. std::string html_tag; + std::string html_id; + std::string html_class; + std::string css_display; // Accessibility functionality of the node inferred from DOM or based on HTML // role attribute. @@ -71,7 +73,7 @@ struct AssistantTree { std::unique_ptr CreateAssistantTree(const AXTreeUpdate& update); -base::string16 AXUrlBaseText(base::string16 url); +std::u16string AXUrlBaseText(std::u16string url); const char* AXRoleToAndroidClassName(ax::mojom::Role role, bool has_parent); } // namespace ui diff --git a/chromium/ui/accessibility/ax_common.h b/chromium/ui/accessibility/ax_common.h index 997ae98b4f2..38f1bfb0b9d 100644 --- a/chromium/ui/accessibility/ax_common.h +++ b/chromium/ui/accessibility/ax_common.h @@ -15,4 +15,27 @@ #define AX_FAIL_FAST_BUILD #endif +// SANITIZER_CHECK's use case is severe, but recoverable situations that need +// priority debugging. They trigger on Clusterfuzz, debug and sanitizer builds. +#if defined(AX_FAIL_FAST_BUILD) +#define SANITIZER_CHECK(val) CHECK(val) +#define SANITIZER_CHECK_EQ(val1, val2) CHECK_EQ(val1, val2) +#define SANITIZER_CHECK_NE(val1, val2) CHECK_NE(val1, val2) +#define SANITIZER_CHECK_LE(val1, val2) CHECK_LE(val1, val2) +#define SANITIZER_CHECK_LT(val1, val2) CHECK_LT(val1, val2) +#define SANITIZER_CHECK_GE(val1, val2) CHECK_GE(val1, val2) +#define SANITIZER_CHECK_GT(val1, val2) CHECK_GT(val1, val2) +#define SANITIZER_NOTREACHED() SANITIZER_CHECK(false) +#else +// Fall back on an ordinary DCHECK. +#define SANITIZER_CHECK(val) DCHECK(val) +#define SANITIZER_CHECK_EQ(val1, val2) DCHECK_EQ(val1, val2) +#define SANITIZER_CHECK_NE(val1, val2) DCHECK_NE(val1, val2) +#define SANITIZER_CHECK_LE(val1, val2) DCHECK_LE(val1, val2) +#define SANITIZER_CHECK_LT(val1, val2) DCHECK_LT(val1, val2) +#define SANITIZER_CHECK_GE(val1, val2) DCHECK_GE(val1, val2) +#define SANITIZER_CHECK_GT(val1, val2) DCHECK_GT(val1, val2) +#define SANITIZER_NOTREACHED() NOTREACHED() +#endif // AX_FAIL_FAST_BUIL + #endif // UI_ACCESSIBILITY_AX_COMMON_H_ diff --git a/chromium/ui/accessibility/ax_enum_util.cc b/chromium/ui/accessibility/ax_enum_util.cc index e2660e79bd6..dcd52498110 100644 --- a/chromium/ui/accessibility/ax_enum_util.cc +++ b/chromium/ui/accessibility/ax_enum_util.cc @@ -340,8 +340,6 @@ const char* ToString(ax::mojom::Role role) { return "iframePresentational"; case ax::mojom::Role::kIgnored: return "ignored"; - case ax::mojom::Role::kImageMap: - return "imageMap"; case ax::mojom::Role::kImage: return "image"; case ax::mojom::Role::kImeCandidate: @@ -760,6 +758,8 @@ const char* ToString(ax::mojom::StringAttribute string_attribute) { return "checkedStateDescription"; case ax::mojom::StringAttribute::kChildTreeId: return "childTreeId"; + case ax::mojom::StringAttribute::kChildTreeNodeAppId: + return "childTreeNodeAppId"; case ax::mojom::StringAttribute::kClassName: return "className"; case ax::mojom::StringAttribute::kContainerLiveRelevant: @@ -792,6 +792,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::kPlaceholder: return "placeholder"; case ax::mojom::StringAttribute::kRole: diff --git a/chromium/ui/accessibility/ax_enum_util_unittest.cc b/chromium/ui/accessibility/ax_enum_util_unittest.cc index 34be7b3df6c..284b68cf2d7 100644 --- a/chromium/ui/accessibility/ax_enum_util_unittest.cc +++ b/chromium/ui/accessibility/ax_enum_util_unittest.cc @@ -103,8 +103,17 @@ TEST(AXEnumUtilTest, Mutation) { TEST(AXEnumUtilTest, StringAttribute) { TestEnumStringConversion(); - TestAXNodeDataSetter( - &AXNodeData::AddStringAttribute, std::string()); + + AXNodeData node_data; + for (int i = static_cast(ax::mojom::StringAttribute::kMinValue) + 1; + i <= static_cast(ax::mojom::StringAttribute::kMaxValue); ++i) { + ax::mojom::StringAttribute attr = + static_cast(i); + if (attr == ax::mojom::StringAttribute::kChildTreeId) + continue; + node_data.AddStringAttribute(attr, std::string()); + } + EXPECT_TRUE(!node_data.ToString().empty()); } TEST(AXEnumUtilTest, IntAttribute) { diff --git a/chromium/ui/accessibility/ax_enums.mojom b/chromium/ui/accessibility/ax_enums.mojom index cd405e5f946..6ff101120cc 100644 --- a/chromium/ui/accessibility/ax_enums.mojom +++ b/chromium/ui/accessibility/ax_enums.mojom @@ -214,7 +214,6 @@ enum Role { kIframePresentational, kIgnored, kImage, - kImageMap, kImeCandidate, kInlineTextBox, kInputTime, @@ -502,6 +501,7 @@ enum StringAttribute { kAutoComplete, kCheckedStateDescription, kChildTreeId, + kChildTreeNodeAppId, kClassName, kContainerLiveRelevant, kContainerLiveStatus, @@ -522,6 +522,7 @@ enum StringAttribute { kName, kLiveRelevant, kLiveStatus, + kParentTreeNodeAppId, // Only if not already exposed in kName (NameFrom::kPlaceholder) kPlaceholder, kRole, diff --git a/chromium/ui/accessibility/ax_event_bundle_sink.h b/chromium/ui/accessibility/ax_event_bundle_sink.h deleted file mode 100644 index 95d6e8a759f..00000000000 --- a/chromium/ui/accessibility/ax_event_bundle_sink.h +++ /dev/null @@ -1,41 +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. - -#ifndef UI_ACCESSIBILITY_AX_EVENT_BUNDLE_SINK_H_ -#define UI_ACCESSIBILITY_AX_EVENT_BUNDLE_SINK_H_ - -#include - -#include "ui/accessibility/ax_export.h" -#include "ui/accessibility/ax_tree_update.h" - -namespace gfx { -class Point; -} // namespace gfx - -namespace ui { - -struct AXEvent; -class AXTreeID; - -// Interface for a consumer of groups of AXEvents. -class AX_EXPORT AXEventBundleSink { - public: - // |tree_id|: ID of the accessibility tree that the events apply to. - // |updates|: Zero or more updates to the accessibility tree to apply first. - // |mouse location|: Current mouse location in screen coordinates. - // |events|: Zero or more events to fire after the updates have been applied. - // Callers may wish to std::move() into the vector params to avoid copies. - virtual void DispatchAccessibilityEvents(const AXTreeID& tree_id, - std::vector updates, - const gfx::Point& mouse_location, - std::vector events) = 0; - - protected: - virtual ~AXEventBundleSink() {} -}; - -} // namespace ui - -#endif // UI_ACCESSIBILITY_AX_EVENT_BUNDLE_SINK_H_ diff --git a/chromium/ui/accessibility/ax_event_generator.cc b/chromium/ui/accessibility/ax_event_generator.cc index 00041032b6e..ebc55f7490f 100644 --- a/chromium/ui/accessibility/ax_event_generator.cc +++ b/chromium/ui/accessibility/ax_event_generator.cc @@ -12,39 +12,17 @@ #include "ui/accessibility/ax_role_properties.h" namespace ui { -namespace { - -bool IsActiveLiveRegion(const AXTreeObserver::Change& change) { - return change.node->data().HasStringAttribute( - ax::mojom::StringAttribute::kLiveStatus) && - change.node->data().GetStringAttribute( - ax::mojom::StringAttribute::kLiveStatus) != "off"; -} -bool IsContainedInLiveRegion(const AXTreeObserver::Change& change) { - return change.node->data().HasStringAttribute( - ax::mojom::StringAttribute::kContainerLiveStatus) && - change.node->data().HasStringAttribute( - ax::mojom::StringAttribute::kName); -} +namespace { bool HasEvent(const std::set& node_events, AXEventGenerator::Event event) { - for (auto& iter : node_events) { - if (iter.event == event) - return true; - } - return false; + return node_events.count(AXEventGenerator::EventParams(event)); } void RemoveEvent(std::set* node_events, AXEventGenerator::Event event) { - for (auto& iter : *node_events) { - if (iter.event == event) { - node_events->erase(iter); - return; - } - } + node_events->erase(AXEventGenerator::EventParams(event)); } // If a node toggled its ignored state, don't also fire children-changed because @@ -88,6 +66,12 @@ bool HasIgnoredChangedState( } // namespace +// +// AXEventGenerator::EventParams +// + +AXEventGenerator::EventParams::EventParams(const Event event) : event(event) {} + AXEventGenerator::EventParams::EventParams( const Event event, const ax::mojom::EventFrom event_from, @@ -102,6 +86,9 @@ AXEventGenerator::EventParams::EventParams(const EventParams& other) = default; AXEventGenerator::EventParams::~EventParams() = default; +AXEventGenerator::EventParams& AXEventGenerator::EventParams::operator=( + const EventParams& other) = default; + bool AXEventGenerator::EventParams::operator==(const EventParams& rhs) const { return rhs.event == event; } @@ -110,17 +97,27 @@ bool AXEventGenerator::EventParams::operator<(const EventParams& rhs) const { return event < rhs.event; } +// +// AXEventGenerator::TargetedEvent +// + AXEventGenerator::TargetedEvent::TargetedEvent(AXNode* node, const EventParams& event_params) : node(node), event_params(event_params) { DCHECK(node); } +AXEventGenerator::TargetedEvent::~TargetedEvent() = default; + +// +// AXEventGenerator::Iterator +// + AXEventGenerator::Iterator::Iterator( - const std::map>& map, - const std::map>::const_iterator& head) - : map_(map), map_iter_(head) { - if (map_iter_ != map.end()) + std::map>::const_iterator map_start_iter, + std::map>::const_iterator map_end_iter) + : map_iter_(map_start_iter), map_end_iter_(map_end_iter) { + if (map_iter_ != map_end_iter_) set_iter_ = map_iter_->second.begin(); } @@ -129,36 +126,77 @@ AXEventGenerator::Iterator::Iterator(const AXEventGenerator::Iterator& other) = AXEventGenerator::Iterator::~Iterator() = default; -bool AXEventGenerator::Iterator::operator!=( - const AXEventGenerator::Iterator& rhs) const { - return map_iter_ != rhs.map_iter_ || - (map_iter_ != map_.end() && set_iter_ != rhs.set_iter_); -} +AXEventGenerator::Iterator& AXEventGenerator::Iterator::operator=( + const Iterator& other) = default; AXEventGenerator::Iterator& AXEventGenerator::Iterator::operator++() { - if (map_iter_ == map_.end()) + if (map_iter_ == map_end_iter_) return *this; DCHECK(set_iter_ != map_iter_->second.end()); set_iter_++; - // |map_| may contain empty sets of events in its entries (i.e. |set_iter_| is - // at the iterator's end). In this case, we want to increment |map_iter_| to - // point to the next entry of |map_| that contains non-empty set of events. - while (map_iter_ != map_.end() && set_iter_ == map_iter_->second.end()) { + // The map pointed to by |map_end_iter_| may contain empty sets of events in + // its entries (i.e. |set_iter_| is at the iterator's end). In this case, we + // want to increment |map_iter_| to point to the next entry of the map that + // contains a non-empty set of events. + while (map_iter_ != map_end_iter_ && set_iter_ == map_iter_->second.end()) { map_iter_++; - if (map_iter_ != map_.end()) + if (map_iter_ != map_end_iter_) set_iter_ = map_iter_->second.begin(); } return *this; } +AXEventGenerator::Iterator AXEventGenerator::Iterator::operator++(int) { + if (map_iter_ == map_end_iter_) + return *this; + Iterator iter = *this; + ++(*this); + return iter; +} + AXEventGenerator::TargetedEvent AXEventGenerator::Iterator::operator*() const { - DCHECK(map_iter_ != map_.end() && set_iter_ != map_iter_->second.end()); + DCHECK(map_iter_ != map_end_iter_); + DCHECK(set_iter_ != map_iter_->second.end()); return AXEventGenerator::TargetedEvent(map_iter_->first, *set_iter_); } +bool operator==(const AXEventGenerator::Iterator& lhs, + const AXEventGenerator::Iterator& rhs) { + if (lhs.map_iter_ == lhs.map_end_iter_ && rhs.map_iter_ == rhs.map_end_iter_) + return true; + return lhs.map_iter_ == rhs.map_iter_ && lhs.set_iter_ == rhs.set_iter_; +} + +bool operator!=(const AXEventGenerator::Iterator& lhs, + const AXEventGenerator::Iterator& rhs) { + return !(lhs == rhs); +} + +void swap(AXEventGenerator::Iterator& lhs, AXEventGenerator::Iterator& rhs) { + if (lhs == rhs) + return; + + std::map>::const_iterator + map_iter = lhs.map_iter_; + lhs.map_iter_ = rhs.map_iter_; + rhs.map_iter_ = map_iter; + std::map>::const_iterator + map_end_iter = lhs.map_end_iter_; + lhs.map_end_iter_ = rhs.map_end_iter_; + rhs.map_end_iter_ = map_end_iter; + std::set::const_iterator set_iter = + lhs.set_iter_; + lhs.set_iter_ = rhs.set_iter_; + rhs.set_iter_ = set_iter; +} + +// +// AXEventGenerator +// + AXEventGenerator::AXEventGenerator() = default; AXEventGenerator::AXEventGenerator(AXTree* tree) : tree_(tree) { @@ -208,11 +246,11 @@ AXEventGenerator::Iterator AXEventGenerator::begin() const { } } - return AXEventGenerator::Iterator(tree_events_, map_iter); + return AXEventGenerator::Iterator(map_iter, tree_events_.end()); } AXEventGenerator::Iterator AXEventGenerator::end() const { - return AXEventGenerator::Iterator(tree_events_, tree_events_.end()); + return AXEventGenerator::Iterator(tree_events_.end(), tree_events_.end()); } void AXEventGenerator::ClearEvents() { @@ -722,9 +760,9 @@ void AXEventGenerator::OnAtomicUpdateFinished( if (IsAlert(change.node->data().role)) AddEvent(change.node, Event::ALERT); - else if (IsActiveLiveRegion(change)) + else if (change.node->data().IsActiveLiveRegionRoot()) AddEvent(change.node, Event::LIVE_REGION_CREATED); - else if (IsContainedInLiveRegion(change)) + else if (change.node->data().IsContainedInActiveLiveRegion()) FireLiveRegionEvents(change.node); } diff --git a/chromium/ui/accessibility/ax_event_generator.h b/chromium/ui/accessibility/ax_event_generator.h index d98b5e39e64..96dbf98525e 100644 --- a/chromium/ui/accessibility/ax_event_generator.h +++ b/chromium/ui/accessibility/ax_event_generator.h @@ -31,6 +31,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { ACTIVE_DESCENDANT_CHANGED, ALERT, ARIA_CURRENT_CHANGED, + // ATK treats alignment, indentation, and other format-related attributes as // text attributes even when they are only applicable to the entire object. // And it lacks an event for use when object attributes have changed. @@ -48,6 +49,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { DOCUMENT_SELECTION_CHANGED, DOCUMENT_TITLE_CHANGED, DROPEFFECT_CHANGED, + // TODO(nektar): Deprecate this event and replace it with // "VALUE_IN_TEXT_FIELD_CHANGED". EDITABLE_TEXT_CHANGED, @@ -65,11 +67,17 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { KEY_SHORTCUTS_CHANGED, LABELED_BY_CHANGED, LANGUAGE_CHANGED, - LAYOUT_INVALIDATED, // Fired when aria-busy turns from true to false. - LIVE_REGION_CHANGED, // Fired on the root of a live region. + LAYOUT_INVALIDATED, // Fired when aria-busy turns from true to false. + + // Fired only on the root of the ARIA live region. + LIVE_REGION_CHANGED, + // Fired only on the root of the ARIA live region. LIVE_REGION_CREATED, - LIVE_REGION_NODE_CHANGED, // Fired on a node within a live region. + // Fired on all the nodes within the ARIA live region excluding its root. + LIVE_REGION_NODE_CHANGED, + // Fired only on the root of the ARIA live region. LIVE_RELEVANT_CHANGED, + // Fired only on the root of the ARIA live region. LIVE_STATUS_CHANGED, LOAD_COMPLETE, LOAD_START, @@ -105,18 +113,19 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { TEXT_ATTRIBUTE_CHANGED, VALUE_IN_TEXT_FIELD_CHANGED, - // This event is for the exact set of attributes that affect - // the MSAA/IAccessible state on Windows. Not needed on other platforms, - // but very natural to compute here. + // This event is fired for the exact set of attributes that affect the + // MSAA/IAccessible state on Windows. It is not needed on other platforms, + // but it is very natural to compute in this class. WIN_IACCESSIBLE_STATE_CHANGED, MAX_VALUE = WIN_IACCESSIBLE_STATE_CHANGED, }; // For distinguishing between show and hide state when a node has - // IGNORED_CHANGED event. + // an IGNORED_CHANGED event. enum class IgnoredChangedState : uint8_t { kShow, kHide, kCount = 2 }; - struct AX_EXPORT EventParams { + struct AX_EXPORT EventParams final { + explicit EventParams(Event event); EventParams(Event event, ax::mojom::EventFrom event_from, ax::mojom::Action event_from_action, @@ -124,21 +133,22 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { EventParams(const EventParams& other); ~EventParams(); + EventParams& operator=(const EventParams& other); bool operator==(const EventParams& rhs) const; bool operator<(const EventParams& rhs) const; Event event; - ax::mojom::EventFrom event_from; + ax::mojom::EventFrom event_from = ax::mojom::EventFrom::kNone; ax::mojom::Action event_from_action; std::vector event_intents; }; - struct TargetedEvent final { - // |node| must not be null - TargetedEvent(ui::AXNode* node, const EventParams& event_params); - ~TargetedEvent() = default; + struct AX_EXPORT TargetedEvent final { + // |node| must not be null. + TargetedEvent(AXNode* node, const EventParams& event_params); + ~TargetedEvent(); - ui::AXNode* node; + AXNode* const node; const EventParams& event_params; }; @@ -146,18 +156,23 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { : public std::iterator { public: Iterator( - const std::map>& map, - const std::map>::const_iterator& head); + std::map>::const_iterator map_start_iter, + std::map>::const_iterator map_end_iter); Iterator(const Iterator& other); ~Iterator(); - bool operator!=(const Iterator& rhs) const; + Iterator& operator=(const Iterator& other); Iterator& operator++(); - TargetedEvent operator*() const; + Iterator operator++(int); // Postfix increment. + value_type operator*() const; private: - const std::map>& map_; + AX_EXPORT friend bool operator==(const Iterator& lhs, const Iterator& rhs); + AX_EXPORT friend bool operator!=(const Iterator& lhs, const Iterator& rhs); + AX_EXPORT friend void swap(Iterator& lhs, Iterator& rhs); + std::map>::const_iterator map_iter_; + std::map>::const_iterator map_end_iter_; std::set::const_iterator set_iter_; }; @@ -192,7 +207,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { // this object or until you call SetTree again. void SetTree(AXTree* new_tree); - // Null |tree_| without accessing it or destroying it. + // Nulls-out |tree_| without accessing it or destroying it. void ReleaseTree(); // @@ -274,11 +289,21 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { const std::vector& changes) override; private: + static void GetRestrictionStates(ax::mojom::Restriction restriction, + bool* is_enabled, + bool* is_readonly); + + // Returns a vector of values unique to either |lhs| or |rhs| + static std::vector ComputeIntListDifference( + const std::vector& lhs, + const std::vector& rhs); + void FireLiveRegionEvents(AXNode* node); void FireActiveDescendantEvents(); void FireValueInTextFieldChangedEvent(AXTree* tree, AXNode* target_node); void FireRelationSourceEvents(AXTree* tree, AXNode* target_node); bool ShouldFireLoadEvents(AXNode* node); + // Remove excessive events for a tree update containing node. // We remove certain events on a node when it flips its IGNORED state to // either show/hide and one of the node's ancestor has also flipped its @@ -298,14 +323,6 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { std::map& ancestor_ignored_changed_map); void PostprocessEvents(); - static void GetRestrictionStates(ax::mojom::Restriction restriction, - bool* is_enabled, - bool* is_readonly); - - // Returns a vector of values unique to either |lhs| or |rhs| - static std::vector ComputeIntListDifference( - const std::vector& lhs, - const std::vector& rhs); AXTree* tree_ = nullptr; // Not owned. std::map> tree_events_; diff --git a/chromium/ui/accessibility/ax_language_detection.cc b/chromium/ui/accessibility/ax_language_detection.cc index 8eed3f994ba..b031e72166a 100644 --- a/chromium/ui/accessibility/ax_language_detection.cc +++ b/chromium/ui/accessibility/ax_language_detection.cc @@ -3,8 +3,10 @@ // found in the LICENSE file. #include "ui/accessibility/ax_language_detection.h" + #include #include +#include #include "base/command_line.h" #include "base/i18n/unicodestring.h" @@ -236,7 +238,8 @@ void AXLanguageDetectionManager::RegisterLanguageDetectionObserver() { // Construct our new Observer as requested. // If there is already an Observer on this Manager then this will destroy it. - language_detection_observer_.reset(new AXLanguageDetectionObserver(tree_)); + language_detection_observer_ = + std::make_unique(tree_); } // Detect languages for each node. diff --git a/chromium/ui/accessibility/ax_node.cc b/chromium/ui/accessibility/ax_node.cc index 49c9dc1515d..4f6ca792e4d 100644 --- a/chromium/ui/accessibility/ax_node.cc +++ b/chromium/ui/accessibility/ax_node.cc @@ -19,13 +19,15 @@ #include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/ax_table_info.h" #include "ui/accessibility/ax_tree.h" +#include "ui/accessibility/ax_tree_manager.h" +#include "ui/accessibility/ax_tree_manager_map.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/transform.h" namespace ui { // Definition of static class members. -constexpr base::char16 AXNode::kEmbeddedCharacter[]; +constexpr char16_t AXNode::kEmbeddedCharacter[]; constexpr int AXNode::kEmbeddedCharacterLength; AXNode::AXNode(AXNode::OwnerTree* tree, @@ -42,38 +44,137 @@ AXNode::AXNode(AXNode::OwnerTree* tree, AXNode::~AXNode() = default; +AXNodeData&& AXNode::TakeData() { + return std::move(data_); +} + +size_t AXNode::GetChildCount() const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + return children_.size(); +} + +size_t AXNode::GetChildCountCrossingTreeBoundary() const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + + const AXTreeManager* child_tree_manager = + AXTreeManagerMap::GetInstance().GetManagerForChildTree(*this); + if (child_tree_manager) { + return 1u; + } + + return GetChildCount(); +} + size_t AXNode::GetUnignoredChildCount() const { - // TODO(nektar): Should DCHECK if the node is not ignored. + // TODO(nektar): Should DCHECK that this node is not ignored. DCHECK(!tree_->GetTreeUpdateInProgressState()); return unignored_child_count_; } -AXNodeData&& AXNode::TakeData() { - return std::move(data_); +size_t AXNode::GetUnignoredChildCountCrossingTreeBoundary() const { + // TODO(nektar): Should DCHECK that this node is not ignored. + DCHECK(!tree_->GetTreeUpdateInProgressState()); + + const AXTreeManager* child_tree_manager = + AXTreeManagerMap::GetInstance().GetManagerForChildTree(*this); + if (child_tree_manager) { + DCHECK_EQ(unignored_child_count_, 0u) + << "A node cannot be hosting both a child tree and other nodes as " + "children."; + return 1u; // A child tree is never ignored. + } + + return unignored_child_count_; +} + +AXNode* AXNode::GetChildAt(size_t index) const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + if (index >= GetChildCount()) + return nullptr; + return children_[index]; +} + +AXNode* AXNode::GetChildAtCrossingTreeBoundary(size_t index) const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + + const AXTreeManager* child_tree_manager = + AXTreeManagerMap::GetInstance().GetManagerForChildTree(*this); + if (child_tree_manager) { + DCHECK_EQ(index, 0u) + << "A node cannot be hosting both a child tree and other nodes as " + "children."; + return child_tree_manager->GetRootAsAXNode(); + } + + return GetChildAt(index); } AXNode* AXNode::GetUnignoredChildAtIndex(size_t index) const { + // TODO(nektar): Should DCHECK that this node is not ignored. DCHECK(!tree_->GetTreeUpdateInProgressState()); - size_t count = 0; + for (auto it = UnignoredChildrenBegin(); it != UnignoredChildrenEnd(); ++it) { - if (count == index) + if (index == 0) return it.get(); - ++count; + --index; + } + + return nullptr; +} + +AXNode* AXNode::GetUnignoredChildAtIndexCrossingTreeBoundary( + size_t index) const { + // TODO(nektar): Should DCHECK that this node is not ignored. + DCHECK(!tree_->GetTreeUpdateInProgressState()); + + const AXTreeManager* child_tree_manager = + AXTreeManagerMap::GetInstance().GetManagerForChildTree(*this); + if (child_tree_manager) { + DCHECK_EQ(index, 0u) + << "A node cannot be hosting both a child tree and other nodes as " + "children."; + // A child tree is never ignored. + return child_tree_manager->GetRootAsAXNode(); } + + return GetUnignoredChildAtIndex(index); +} + +AXNode* AXNode::GetParent() const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + return parent_; +} + +AXNode* AXNode::GetParentCrossingTreeBoundary() const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + if (parent_) + return parent_; + const AXTreeManager* manager = + AXTreeManagerMap::GetInstance().GetManager(tree_->GetAXTreeID()); + if (manager) + return manager->GetParentNodeFromParentTreeAsAXNode(); return nullptr; } AXNode* AXNode::GetUnignoredParent() const { DCHECK(!tree_->GetTreeUpdateInProgressState()); - AXNode* result = parent(); - while (result && result->IsIgnored()) - result = result->parent(); - return result; + AXNode* unignored_parent = parent(); + while (unignored_parent && unignored_parent->IsIgnored()) + unignored_parent = unignored_parent->parent(); + + return unignored_parent; } -size_t AXNode::GetUnignoredIndexInParent() const { +AXNode* AXNode::GetUnignoredParentCrossingTreeBoundary() const { DCHECK(!tree_->GetTreeUpdateInProgressState()); - return unignored_index_in_parent_; + AXNode* unignored_parent = GetUnignoredParent(); + if (!unignored_parent) { + const AXTreeManager* manager = + AXTreeManagerMap::GetInstance().GetManager(tree_->GetAXTreeID()); + if (manager) + unignored_parent = manager->GetParentNodeFromParentTreeAsAXNode(); + } + return unignored_parent; } size_t AXNode::GetIndexInParent() const { @@ -81,6 +182,11 @@ size_t AXNode::GetIndexInParent() const { return index_in_parent_; } +size_t AXNode::GetUnignoredIndexInParent() const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); + return unignored_index_in_parent_; +} + AXNode* AXNode::GetFirstUnignoredChild() const { DCHECK(!tree_->GetTreeUpdateInProgressState()); return ComputeFirstUnignoredChildRecursive(); @@ -464,7 +570,7 @@ void AXNode::ComputeLineStartOffsets(std::vector* line_offsets, line_offsets->push_back(*start_offset); } - base::string16 text = + std::u16string text = child->data().GetString16Attribute(ax::mojom::StringAttribute::kName); *start_offset += static_cast(text.length()); } @@ -504,7 +610,7 @@ const std::string& AXNode::GetInheritedStringAttribute( return base::EmptyString(); } -base::string16 AXNode::GetInheritedString16Attribute( +std::u16string AXNode::GetInheritedString16Attribute( ax::mojom::StringAttribute attribute) const { return base::UTF8ToUTF16(GetInheritedStringAttribute(attribute)); } @@ -521,7 +627,7 @@ void AXNode::ClearLanguageInfo() { language_info_.reset(); } -base::string16 AXNode::GetHypertext() const { +std::u16string AXNode::GetHypertext() const { DCHECK(!tree_->GetTreeUpdateInProgressState()); // Hypertext is not exposed for descendants of leaf nodes. For such nodes, @@ -549,9 +655,9 @@ base::string16 AXNode::GetHypertext() const { // // Note that the word "hypertext" comes from the IAccessible2 Standard and has // nothing to do with HTML. - const base::string16 embedded_character_str(kEmbeddedCharacter); + const std::u16string embedded_character_str(kEmbeddedCharacter); DCHECK_EQ(int{embedded_character_str.length()}, kEmbeddedCharacterLength); - base::string16 hypertext; + 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 @@ -568,15 +674,27 @@ base::string16 AXNode::GetHypertext() const { std::string AXNode::GetInnerText() const { DCHECK(!tree_->GetTreeUpdateInProgressState()); + // Special case, if a node is hosting another accessibility tree, cross the + // tree boundary and return the inner text that is found in that other tree. + // (A node cannot be hosting an accessibility tree as well as having children + // of its own.) + const AXNode* node = this; + const AXTreeManager* child_tree_manager = + AXTreeManagerMap::GetInstance().GetManagerForChildTree(*node); + if (child_tree_manager) { + node = child_tree_manager->GetRootAsAXNode(); + DCHECK(node) << "All child trees should have a non-null rootnode."; + } + // If a text field has no descendants, then we compute its inner text from its // 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 = - (data().IsTextField() && !GetUnignoredChildCount()); + (node->data().IsTextField() && !node->GetUnignoredChildCount()); if (is_plain_text_field_without_descendants) { std::string value = - data().GetStringAttribute(ax::mojom::StringAttribute::kValue); + node->data().GetStringAttribute(ax::mojom::StringAttribute::kValue); // If the value is empty, then there might be some placeholder text in the // text field, or any other name that is derived from visible contents, even // if the text field has no children. @@ -589,9 +707,9 @@ std::string AXNode::GetInnerText() const { // 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 = - (data().IsTextField() && GetUnignoredChildCount()); - if (IsLeaf() && !is_plain_text_field_with_descendants) { - switch (data().GetNameFrom()) { + (node->data().IsTextField() && node->GetUnignoredChildCount()); + if (node->IsLeaf() && !is_plain_text_field_with_descendants) { + switch (node->data().GetNameFrom()) { case ax::mojom::NameFrom::kNone: case ax::mojom::NameFrom::kUninitialized: // The accessible name is not displayed on screen, e.g. aria-label, or is @@ -616,35 +734,52 @@ std::string AXNode::GetInnerText() const { // The value attribute takes the place of the node's inner text, e.g. the // value of a submit button is displayed inside the button itself. case ax::mojom::NameFrom::kValue: - return data().GetStringAttribute(ax::mojom::StringAttribute::kName); + return node->data().GetStringAttribute( + ax::mojom::StringAttribute::kName); } } std::string inner_text; - for (auto it = UnignoredChildrenBegin(); it != UnignoredChildrenEnd(); ++it) { + for (auto it = node->UnignoredChildrenBegin(); + it != node->UnignoredChildrenEnd(); ++it) { inner_text += it->GetInnerText(); } return inner_text; } int AXNode::GetInnerTextLength() const { + DCHECK(!tree_->GetTreeUpdateInProgressState()); // This is an optimized version of `AXNode::GetInnerText()`.length(). Instead // of concatenating the strings in GetInnerText() to then get their length, we // sum the lengths of the individual strings. This is faster than // concatenating the strings first and then taking their length, especially // when the process is recursive. + // Special case, if a node is hosting another accessibility tree, cross the + // tree boundary and return the inner text that is found in that other tree. + // (A node cannot be hosting an accessibility tree as well as having children + // of its own.) + const AXNode* node = this; + const AXTreeManager* child_tree_manager = + AXTreeManagerMap::GetInstance().GetManagerForChildTree(*node); + if (child_tree_manager) { + node = child_tree_manager->GetRootAsAXNode(); + DCHECK(node) << "All child trees should have a non-null rootnode."; + } + const bool is_plain_text_field_with_descendants = - (data().IsTextField() && GetUnignoredChildCount()); + (node->data().IsTextField() && node->GetUnignoredChildCount()); // Plain 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 (IsLeaf() && !is_plain_text_field_with_descendants) - return int{GetInnerText().length()}; + if (node->IsLeaf() && !is_plain_text_field_with_descendants) + return int{node->GetInnerText().length()}; int inner_text_length = 0; - for (auto it = UnignoredChildrenBegin(); it != UnignoredChildrenEnd(); ++it) + for (auto it = node->UnignoredChildrenBegin(); + it != node->UnignoredChildrenEnd(); ++it) { inner_text_length += it->GetInnerTextLength(); + } return inner_text_length; } @@ -1364,11 +1499,12 @@ bool AXNode::IsLeaf() const { // contents. See https://crbug.com/689204. // So we decided to not enforce the leafiness of buttons and expose all // children. + // Images are not leaves because the same role is used for image maps, + // which can have link and/or text children. case ax::mojom::Role::kButton: return false; case ax::mojom::Role::kDocCover: case ax::mojom::Role::kGraphicsSymbol: - case ax::mojom::Role::kImage: case ax::mojom::Role::kMeter: case ax::mojom::Role::kScrollBar: case ax::mojom::Role::kSlider: diff --git a/chromium/ui/accessibility/ax_node.h b/chromium/ui/accessibility/ax_node.h index 913c35898ce..2a5841c04f8 100644 --- a/chromium/ui/accessibility/ax_node.h +++ b/chromium/ui/accessibility/ax_node.h @@ -13,7 +13,7 @@ #include #include "base/optional.h" -#include "base/strings/string16.h" +#include "base/strings/char_traits.h" #include "build/build_config.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/ax_export.h" @@ -38,14 +38,11 @@ class AX_EXPORT AXNode final { // actual text contents. Also on the same platforms, if a node has only // ignored descendants, i.e., it appears to be empty to assistive software, we // need to treat it as a character and a word boundary. - // - // Note that we cannot use L"..." because it works correctly only on Windows. - // TODO(nektar): Consider using UTF8 encoding instead, "\xEF\xBF\xBC". - static constexpr base::char16 kEmbeddedCharacter[] = {0xFFFC, 0x0000}; + static constexpr char16_t kEmbeddedCharacter[] = u"\uFFFC"; // We compute the embedded character's length instead of manually typing it in // order to avoid the two variables getting out of sync in a future update. static constexpr int kEmbeddedCharacterLength = - int{sizeof(kEmbeddedCharacter) / sizeof(base::char16) - 1}; + base::CharTraits::length(kEmbeddedCharacter); // Interface to the tree class that owns an AXNode. We use this instead // of letting AXNode have a pointer to its AXTree directly so that we're @@ -125,12 +122,30 @@ class AX_EXPORT AXNode final { // Returns ownership of |data_| to the caller; effectively clearing |data_|. AXNodeData&& TakeData(); - // Walking the tree skipping ignored nodes. + // + // Methods for walking the tree. + // + + size_t GetChildCount() const; + // TODO(nektar): Update `BrowserAccessibility` and remove this method. + size_t GetChildCountCrossingTreeBoundary() const; size_t GetUnignoredChildCount() const; + // TODO(nektar): Update `BrowserAccessibility` and remove this method. + size_t GetUnignoredChildCountCrossingTreeBoundary() const; + AXNode* GetChildAt(size_t index) const; + // TODO(nektar): Update `BrowserAccessibility` and remove this method. + AXNode* GetChildAtCrossingTreeBoundary(size_t index) const; AXNode* GetUnignoredChildAtIndex(size_t index) const; + // TODO(nektar): Update `BrowserAccessibility` and remove this method. + AXNode* GetUnignoredChildAtIndexCrossingTreeBoundary(size_t index) const; + AXNode* GetParent() const; + // TODO(nektar): Update `BrowserAccessibility` and remove this method. + AXNode* GetParentCrossingTreeBoundary() const; AXNode* GetUnignoredParent() const; - size_t GetUnignoredIndexInParent() const; + // TODO(nektar): Update `BrowserAccessibility` and remove this method. + AXNode* GetUnignoredParentCrossingTreeBoundary() const; size_t GetIndexInParent() const; + size_t GetUnignoredIndexInParent() const; AXNode* GetFirstUnignoredChild() const; AXNode* GetLastUnignoredChild() const; AXNode* GetDeepestFirstUnignoredChild() const; @@ -258,10 +273,10 @@ class AX_EXPORT AXNode final { } bool GetString16Attribute(ax::mojom::StringAttribute attribute, - base::string16* value) const { + std::u16string* value) const { return data().GetString16Attribute(attribute, value); } - base::string16 GetString16Attribute( + std::u16string GetString16Attribute( ax::mojom::StringAttribute attribute) const { return data().GetString16Attribute(attribute); } @@ -290,7 +305,7 @@ class AX_EXPORT AXNode final { return data().GetStringListAttribute(attribute, value); } - bool GetHtmlAttribute(const char* attribute, base::string16* value) const { + bool GetHtmlAttribute(const char* attribute, std::u16string* value) const { return data().GetHtmlAttribute(attribute, value); } bool GetHtmlAttribute(const char* attribute, std::string* value) const { @@ -317,7 +332,7 @@ class AX_EXPORT AXNode final { const std::string& GetInheritedStringAttribute( ax::mojom::StringAttribute attribute) const; - base::string16 GetInheritedString16Attribute( + std::u16string GetInheritedString16Attribute( ax::mojom::StringAttribute attribute) const; // If this node is a leaf, returns the inner text of this node. This is @@ -330,7 +345,7 @@ class AX_EXPORT AXNode final { // ATK and IAccessible2 APIs. // // TODO(nektar): Consider changing the return value to std::string. - base::string16 GetHypertext() const; + std::u16string GetHypertext() const; // Returns the text that is found inside this node and all its descendants; // including text found in embedded objects. diff --git a/chromium/ui/accessibility/ax_node_data.cc b/chromium/ui/accessibility/ax_node_data.cc index 7d20441ec0b..6ce31b37e3a 100644 --- a/chromium/ui/accessibility/ax_node_data.cc +++ b/chromium/ui/accessibility/ax_node_data.cc @@ -19,6 +19,7 @@ #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_role_properties.h" +#include "ui/accessibility/ax_tree_id.h" #include "ui/gfx/transform.h" namespace ui { @@ -354,16 +355,16 @@ bool AXNodeData::GetStringAttribute(ax::mojom::StringAttribute attribute, return false; } -base::string16 AXNodeData::GetString16Attribute( +std::u16string AXNodeData::GetString16Attribute( ax::mojom::StringAttribute attribute) const { std::string value_utf8; if (!GetStringAttribute(attribute, &value_utf8)) - return base::string16(); + return std::u16string(); return base::UTF8ToUTF16(value_utf8); } bool AXNodeData::GetString16Attribute(ax::mojom::StringAttribute attribute, - base::string16* value) const { + std::u16string* value) const { std::string value_utf8; if (!GetStringAttribute(attribute, &value_utf8)) return false; @@ -439,7 +440,7 @@ bool AXNodeData::GetHtmlAttribute(const char* html_attr, } bool AXNodeData::GetHtmlAttribute(const char* html_attr, - base::string16* value) const { + std::u16string* value) const { std::string value_utf8; if (!GetHtmlAttribute(html_attr, &value_utf8)) return false; @@ -450,11 +451,21 @@ bool AXNodeData::GetHtmlAttribute(const char* html_attr, void AXNodeData::AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string& value) { DCHECK_NE(attribute, ax::mojom::StringAttribute::kNone); + DCHECK_NE(attribute, ax::mojom::StringAttribute::kChildTreeId) + << "Use AddChildTreeId"; if (HasStringAttribute(attribute)) RemoveStringAttribute(attribute); string_attributes.push_back(std::make_pair(attribute, value)); } +void AXNodeData::AddChildTreeId(const ui::AXTreeID& tree_id) { + ax::mojom::StringAttribute attribute = + ax::mojom::StringAttribute::kChildTreeId; + if (HasStringAttribute(attribute)) + RemoveStringAttribute(attribute); + string_attributes.push_back(std::make_pair(attribute, tree_id.ToString())); +} + void AXNodeData::AddIntAttribute(ax::mojom::IntAttribute attribute, int value) { DCHECK_NE(attribute, ax::mojom::IntAttribute::kNone); if (HasIntAttribute(attribute)) @@ -608,7 +619,7 @@ void AXNodeData::SetName(const std::string& name) { } } -void AXNodeData::SetName(const base::string16& name) { +void AXNodeData::SetName(const std::u16string& name) { SetName(base::UTF16ToUTF8(name)); } @@ -620,7 +631,7 @@ void AXNodeData::SetDescription(const std::string& description) { AddStringAttribute(ax::mojom::StringAttribute::kDescription, description); } -void AXNodeData::SetDescription(const base::string16& description) { +void AXNodeData::SetDescription(const std::u16string& description) { SetDescription(base::UTF16ToUTF8(description)); } @@ -628,7 +639,7 @@ void AXNodeData::SetValue(const std::string& value) { AddStringAttribute(ax::mojom::StringAttribute::kValue, value); } -void AXNodeData::SetValue(const base::string16& value) { +void AXNodeData::SetValue(const std::u16string& value) { SetValue(base::UTF16ToUTF8(value)); } @@ -925,6 +936,15 @@ bool AXNodeData::IsActivatable() const { return IsTextField() || role == ax::mojom::Role::kListBox; } +bool AXNodeData::IsActiveLiveRegionRoot() const { + std::string aria_live_status; + if (GetStringAttribute(ax::mojom::StringAttribute::kLiveStatus, + &aria_live_status)) { + return aria_live_status != "off"; + } + return false; +} + bool AXNodeData::IsButtonPressed() const { // Currently there is no internal representation for |aria-pressed|, and // we map |aria-pressed="true"| to ax::mojom::CheckedState::kTrue for a native @@ -947,6 +967,16 @@ bool AXNodeData::IsClickable() const { return ui::IsClickable(role); } +bool AXNodeData::IsContainedInActiveLiveRegion() const { + std::string aria_container_live_status; + if (GetStringAttribute(ax::mojom::StringAttribute::kContainerLiveStatus, + &aria_container_live_status)) { + return aria_container_live_status != "off" && + HasStringAttribute(ax::mojom::StringAttribute::kName); + } + return false; +} + bool AXNodeData::IsSelectable() const { // It's selectable if it has the attribute, whether it's true or false. return HasBoolAttribute(ax::mojom::BoolAttribute::kSelected) && @@ -1460,6 +1490,9 @@ std::string AXNodeData::ToString() const { case ax::mojom::StringAttribute::kChildTreeId: result += " child_tree_id=" + value.substr(0, 8); break; + case ax::mojom::StringAttribute::kChildTreeNodeAppId: + result += " child_tree_node_app_id=" + value.substr(0, 8); + break; case ax::mojom::StringAttribute::kClassName: result += " class_name=" + value; break; @@ -1507,6 +1540,9 @@ 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); + break; case ax::mojom::StringAttribute::kPlaceholder: result += " placeholder=" + value; break; diff --git a/chromium/ui/accessibility/ax_node_data.h b/chromium/ui/accessibility/ax_node_data.h index d5b466a7d20..0dabcb6ae55 100644 --- a/chromium/ui/accessibility/ax_node_data.h +++ b/chromium/ui/accessibility/ax_node_data.h @@ -13,7 +13,6 @@ #include #include -#include "base/strings/string16.h" #include "base/strings/string_split.h" #include "ui/accessibility/ax_base_export.h" #include "ui/accessibility/ax_enums.mojom-forward.h" @@ -23,6 +22,8 @@ namespace ui { +class AXTreeID; + // Defines the type used for AXNode IDs. using AXNodeID = int32_t; @@ -69,7 +70,7 @@ struct AX_BASE_EXPORT AXNodeData { // need to distinguish between the default value and a missing attribute), // and another that returns the default value for that type if the // attribute is not present. In addition, strings can be returned as - // either std::string or base::string16, for convenience. + // either std::string or std::u16string, for convenience. bool HasBoolAttribute(ax::mojom::BoolAttribute attribute) const; bool GetBoolAttribute(ax::mojom::BoolAttribute attribute) const; @@ -91,8 +92,8 @@ struct AX_BASE_EXPORT AXNodeData { std::string* value) const; bool GetString16Attribute(ax::mojom::StringAttribute attribute, - base::string16* value) const; - base::string16 GetString16Attribute( + std::u16string* value) const; + std::u16string GetString16Attribute( ax::mojom::StringAttribute attribute) const; bool HasIntListAttribute(ax::mojom::IntListAttribute attribute) const; @@ -107,7 +108,7 @@ struct AX_BASE_EXPORT AXNodeData { bool GetStringListAttribute(ax::mojom::StringListAttribute attribute, std::vector* value) const; - bool GetHtmlAttribute(const char* attribute, base::string16* value) const; + bool GetHtmlAttribute(const char* attribute, std::u16string* value) const; bool GetHtmlAttribute(const char* attribute, std::string* value) const; // @@ -118,8 +119,11 @@ struct AX_BASE_EXPORT AXNodeData { // have wanted or what existing code already assumes. // + // This method cannot be used to set kChildTreeId due to a common + // misuse of base::UnguessableToken serialization. Use AddChildTreeId instead. void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string& value); + void AddChildTreeId(const ui::AXTreeID& tree_id); void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value); void AddFloatAttribute(ax::mojom::FloatAttribute attribute, float value); void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value); @@ -151,18 +155,18 @@ struct AX_BASE_EXPORT AXNodeData { // Adds the name attribute or replaces it if already present. Also sets the // NameFrom attribute if not already set. void SetName(const std::string& name); - void SetName(const base::string16& name); + void SetName(const std::u16string& name); // Allows nameless objects to pass accessibility checks. void SetNameExplicitlyEmpty(); // Adds the description attribute or replaces it if already present. void SetDescription(const std::string& description); - void SetDescription(const base::string16& description); + void SetDescription(const std::u16string& description); // Adds the value attribute or replaces it if already present. void SetValue(const std::string& value); - void SetValue(const base::string16& value); + void SetValue(const std::u16string& value); // Returns true if the given enum bit is 1. bool HasState(ax::mojom::State state) const; @@ -213,6 +217,10 @@ struct AX_BASE_EXPORT AXNodeData { // clicked, such as a text field or a native HTML list box. bool IsActivatable() const; + // Helper to determine if the data belongs to a node that is at the root of an + // ARIA live region that is active, i.e. its status is not set to "off". + bool IsActiveLiveRegionRoot() const; + // Helper to determine if the data belongs to a node that is a native button // or ARIA role="button" in a pressed state. bool IsButtonPressed() const; @@ -221,6 +229,10 @@ struct AX_BASE_EXPORT AXNodeData { // clicks. bool IsClickable() const; + // Helper to determine if the data belongs to a node that is part of an active + // ARIA live region, and for which live announcements should be made. + bool IsContainedInActiveLiveRegion() const; + // Helper to determine if the object is selectable. bool IsSelectable() const; diff --git a/chromium/ui/accessibility/ax_node_position_unittest.cc b/chromium/ui/accessibility/ax_node_position_unittest.cc index 23296741f08..2f14e80355d 100644 --- a/chromium/ui/accessibility/ax_node_position_unittest.cc +++ b/chromium/ui/accessibility/ax_node_position_unittest.cc @@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/callback.h" #include "base/strings/strcat.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -418,8 +417,7 @@ void AXPositionTest::SetUp() { SetTree(std::make_unique(initial_state)); AXTreeUpdate views_tree_update; - web_view.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - GetTreeID().ToString()); + web_view.AddChildTreeId(GetTreeID()); views_tree_update.nodes = {web_view}; ASSERT_TRUE(views_tree->Unserialize(views_tree_update)); views_tree_manager_ = TestAXTreeManager(std::move(views_tree)); @@ -588,14 +586,12 @@ void AXPositionTest::CreateBrowserWindow( CreateAXTree({iframe_root}, webpage_tree->GetAXTreeID()); AXTreeUpdate views_tree_update; - web_view.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - webpage_tree->GetAXTreeID().ToString()); + web_view.AddChildTreeId(webpage_tree->GetAXTreeID()); views_tree_update.nodes = {web_view}; ASSERT_TRUE(views_tree->Unserialize(views_tree_update)); AXTreeUpdate webpage_tree_update; - iframe.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - iframe_tree->GetAXTreeID().ToString()); + iframe.AddChildTreeId(iframe_tree->GetAXTreeID()); webpage_tree_update.nodes = {iframe}; ASSERT_TRUE(webpage_tree->Unserialize(webpage_tree_update)); @@ -609,27 +605,27 @@ std::unique_ptr AXPositionTest::CreateMultilingualDocument( EXPECT_NE(nullptr, text_offsets); text_offsets->push_back(0); - base::string16 english_text; + std::u16string english_text; for (int i = 0; i < 3; ++i) { - base::string16 grapheme = base::WideToUTF16(kGraphemeClusters[i]); + std::u16string grapheme = base::WideToUTF16(kGraphemeClusters[i]); EXPECT_EQ(1u, grapheme.length()) << "All English characters should be one UTF16 code unit in length."; text_offsets->push_back(text_offsets->back() + int{grapheme.length()}); english_text.append(grapheme); } - base::string16 hindi_text; + std::u16string hindi_text; for (int i = 3; i < 5; ++i) { - base::string16 grapheme = base::WideToUTF16(kGraphemeClusters[i]); + std::u16string grapheme = base::WideToUTF16(kGraphemeClusters[i]); EXPECT_LE(2u, grapheme.length()) << "All Hindi characters should be two " "or more UTF16 code units in length."; text_offsets->push_back(text_offsets->back() + int{grapheme.length()}); hindi_text.append(grapheme); } - base::string16 thai_text; + std::u16string thai_text; for (int i = 5; i < 8; ++i) { - base::string16 grapheme = base::WideToUTF16(kGraphemeClusters[i]); + std::u16string grapheme = base::WideToUTF16(kGraphemeClusters[i]); EXPECT_LT(0u, grapheme.length()) << "One of the Thai characters should be one UTF16 code unit, " "whilst others should be two or more."; @@ -809,7 +805,7 @@ TEST_F(AXPositionTest, ToString) { AXNodeData static_text_data_2; static_text_data_2.id = 3; static_text_data_2.role = ax::mojom::Role::kStaticText; - static_text_data_2.SetName(base::WideToUTF16(L"\xfffc")); + static_text_data_2.SetName(u"\xfffc"); AXNodeData static_text_data_3; static_text_data_3.id = 4; @@ -1064,7 +1060,7 @@ TEST_F(AXPositionTest, GetTextFromNullPosition) { TestPositionType text_position = AXNodePosition::CreateNullPosition(); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsNullPosition()); - ASSERT_EQ(base::WideToUTF16(L""), text_position->GetText()); + ASSERT_EQ(u"", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromRoot) { @@ -1073,7 +1069,7 @@ TEST_F(AXPositionTest, GetTextFromRoot) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L"Line 1\nLine 2"), text_position->GetText()); + ASSERT_EQ(u"Line 1\nLine 2", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromButton) { @@ -1082,7 +1078,7 @@ TEST_F(AXPositionTest, GetTextFromButton) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L""), text_position->GetText()); + ASSERT_EQ(u"", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromCheckbox) { @@ -1091,7 +1087,7 @@ TEST_F(AXPositionTest, GetTextFromCheckbox) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L""), text_position->GetText()); + ASSERT_EQ(u"", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromTextField) { @@ -1100,7 +1096,7 @@ TEST_F(AXPositionTest, GetTextFromTextField) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L"Line 1\nLine 2"), text_position->GetText()); + ASSERT_EQ(u"Line 1\nLine 2", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromStaticText) { @@ -1109,7 +1105,7 @@ TEST_F(AXPositionTest, GetTextFromStaticText) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L"Line 1"), text_position->GetText()); + ASSERT_EQ(u"Line 1", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromInlineTextBox) { @@ -1118,7 +1114,7 @@ TEST_F(AXPositionTest, GetTextFromInlineTextBox) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L"Line 1"), text_position->GetText()); + ASSERT_EQ(u"Line 1", text_position->GetText()); } TEST_F(AXPositionTest, GetTextFromLineBreak) { @@ -1127,7 +1123,7 @@ TEST_F(AXPositionTest, GetTextFromLineBreak) { ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); ASSERT_TRUE(text_position->IsTextPosition()); - ASSERT_EQ(base::WideToUTF16(L"\n"), text_position->GetText()); + ASSERT_EQ(u"\n", text_position->GetText()); } TEST_F(AXPositionTest, GetMaxTextOffsetFromNullPosition) { @@ -1300,7 +1296,7 @@ TEST_F(AXPositionTest, GetMaxTextOffsetAndGetTextWithGeneratedContent) { ASSERT_NE(nullptr, text_position); EXPECT_TRUE(text_position->IsTextPosition()); EXPECT_EQ(38, text_position->MaxTextOffset()); - EXPECT_EQ(base::WideToUTF16(L"Placeholder from generated content3.14"), + EXPECT_EQ(u"Placeholder from generated content3.14", text_position->GetText()); } @@ -10944,7 +10940,7 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) { EXPECT_EQ(inline_box_7.id, result_position->anchor_id()); EXPECT_EQ(1, result_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity()); - EXPECT_EQ(base::WideToUTF16(L" world"), result_position->GetText()); + EXPECT_EQ(u" world", result_position->GetText()); // CreatePreviousWordStartPosition tests. position = std::move(result_position); @@ -10963,7 +10959,7 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) { EXPECT_EQ(inline_box_3.id, result_position->anchor_id()); EXPECT_EQ(0, result_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity()); - EXPECT_EQ(base::WideToUTF16(L"Hello "), result_position->GetText()); + EXPECT_EQ(u"Hello ", result_position->GetText()); // CreateNextWordEndPosition tests. position = std::move(result_position); @@ -10973,7 +10969,7 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) { EXPECT_EQ(inline_box_3.id, result_position->anchor_id()); EXPECT_EQ(6, result_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity()); - EXPECT_EQ(base::WideToUTF16(L"Hello "), result_position->GetText()); + EXPECT_EQ(u"Hello ", result_position->GetText()); position = std::move(result_position); result_position = @@ -10994,7 +10990,7 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) { EXPECT_EQ(inline_box_7.id, result_position->anchor_id()); EXPECT_EQ(6, result_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity()); - EXPECT_EQ(base::WideToUTF16(L" world"), result_position->GetText()); + EXPECT_EQ(u" world", result_position->GetText()); // CreatePreviousWordEndPosition tests. position = std::move(result_position); @@ -11016,7 +11012,7 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) { EXPECT_EQ(inline_box_3.id, result_position->anchor_id()); EXPECT_EQ(6, result_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, result_position->affinity()); - EXPECT_EQ(base::WideToUTF16(L"Hello "), result_position->GetText()); + EXPECT_EQ(u"Hello ", result_position->GetText()); // Positions on descendants of empty objects that have been replaced by the // "embedded object replacement character" are valid, to allow for navigating @@ -11035,11 +11031,10 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) { ax::mojom::TextAffinity::kDownstream); // Hello worldhey - base::string16 expected_text = - base::StrCat({STRING16_LITERAL("Hello "), AXNode::kEmbeddedCharacter, - STRING16_LITERAL(" world"), AXNode::kEmbeddedCharacter, - AXNode::kEmbeddedCharacter, STRING16_LITERAL("hey"), - AXNode::kEmbeddedCharacter}); + std::u16string expected_text = + base::StrCat({u"Hello ", AXNode::kEmbeddedCharacter, u" world", + AXNode::kEmbeddedCharacter, AXNode::kEmbeddedCharacter, + u"hey", AXNode::kEmbeddedCharacter}); EXPECT_EQ(expected_text, position->GetText()); // A position on an empty object that has been replaced by an "embedded object @@ -11143,8 +11138,7 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterEmbedObject) { root.child_ids = {embed_object.id}; embed_object.role = ax::mojom::Role::kEmbeddedObject; - embed_object.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - child_tree_id.ToString()); + embed_object.AddChildTreeId(child_tree_id); SetTree(CreateAXTree({root, embed_object})); // Create tree manager for child tree. diff --git a/chromium/ui/accessibility/ax_position.h b/chromium/ui/accessibility/ax_position.h index c25deec373c..1cc3f1d0a9e 100644 --- a/chromium/ui/accessibility/ax_position.h +++ b/chromium/ui/accessibility/ax_position.h @@ -20,7 +20,6 @@ #include "base/containers/stack.h" #include "base/i18n/break_iterator.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -37,45 +36,6 @@ namespace ui { -namespace { - -// Returns the parent node of the provided child. Returns the parent node's tree -// id and node id through the provided output parameters,|parent_tree_id| and -// |parent_id|. -AXNode* GetParent(AXNode* child, - AXTreeID child_tree_id, - AXTreeID* parent_tree_id, - AXNodeID* parent_id) { - DCHECK(parent_tree_id); - DCHECK(parent_id); - *parent_tree_id = AXTreeIDUnknown(); - *parent_id = kInvalidAXNodeID; - if (!child) - return nullptr; - - AXNode* parent = child->parent(); - *parent_tree_id = child_tree_id; - - if (!parent) { - AXTreeManager* manager = - AXTreeManagerMap::GetInstance().GetManager(child_tree_id); - if (manager) { - parent = manager->GetParentNodeFromParentTreeAsAXNode(); - *parent_tree_id = manager->GetParentTreeID(); - } - } - - if (!parent) { - *parent_tree_id = AXTreeIDUnknown(); - return parent; - } - - *parent_id = parent->id(); - return parent; -} - -} // namespace - // Defines the type of position in the accessibility tree. // A tree position is used when referring to a specific child of a node in the // accessibility tree. @@ -369,16 +329,16 @@ class AXPosition { if (!IsTextPosition() || text_offset_ > MaxTextOffset()) return str; - const base::string16 text = GetText(); + const std::u16string text = GetText(); DCHECK_GE(text_offset_, 0); const size_t max_text_offset = text.size(); DCHECK_LE(text_offset_, int{max_text_offset}) << text; - base::string16 annotated_text; + std::u16string annotated_text; if (text_offset_ == int{max_text_offset}) { - annotated_text = text + base::WideToUTF16(L"<>"); + annotated_text = text + u"<>"; } else { - annotated_text = text.substr(0, text_offset_) + base::WideToUTF16(L"<") + - text[text_offset_] + base::WideToUTF16(L">") + + annotated_text = text.substr(0, text_offset_) + u"<" + + text[text_offset_] + u">" + text.substr(text_offset_ + 1); } @@ -388,10 +348,16 @@ class AXPosition { AXTreeID tree_id() const { return tree_id_; } AXNodeID anchor_id() const { return anchor_id_; } - AXNodeType* GetAnchor() const { + AXNode* GetAnchor() const { if (tree_id_ == AXTreeIDUnknown() || anchor_id_ == kInvalidAXNodeID) return nullptr; - return GetNodeInTree(tree_id_, anchor_id_); + + const AXTreeManager* manager = + AXTreeManagerMap::GetInstance().GetManager(tree_id()); + if (manager) + return manager->GetNodeFromTree(tree_id(), anchor_id()); + + return nullptr; } int GetAnchorSiblingCount() const { @@ -619,12 +585,11 @@ class AXPosition { if (text_position->AtEndOfAnchor() && !text_position->AtEndOfTextSpan() && text_position->IsInWhiteSpace() && - GetNextOnLineID(text_position->anchor_id_) == kInvalidAXNodeID) { + text_position->GetNextOnLineID() == kInvalidAXNodeID) { return true; } - return GetPreviousOnLineID(text_position->anchor_id_) == - kInvalidAXNodeID && + return text_position->GetPreviousOnLineID() == kInvalidAXNodeID && text_position->AtStartOfAnchor(); } } @@ -681,11 +646,10 @@ class AXPosition { // in most but not all cases, the parent of an inline text box is a // static text object, whose end signifies the end of the text span. One // exception is line breaks. - if (GetNextOnLineID(text_position->anchor_id_) == kInvalidAXNodeID) { + if (text_position->GetNextOnLineID() == kInvalidAXNodeID) { return (!text_position->AtEndOfTextSpan() && text_position->IsInWhiteSpace() && - GetPreviousOnLineID(text_position->anchor_id_) != - kInvalidAXNodeID) + text_position->GetPreviousOnLineID() != kInvalidAXNodeID) ? text_position->AtStartOfAnchor() : text_position->AtEndOfAnchor(); } @@ -1087,16 +1051,16 @@ class AXPosition { // This method finds the lowest common ancestor node in the accessibility tree // of this and |other| positions' anchor nodes. - AXNodeType* LowestCommonAnchor(const AXPosition& other) const { + AXNode* LowestCommonAnchor(const AXPosition& other) const { if (IsNullPosition() || other.IsNullPosition()) return nullptr; if (GetAnchor() == other.GetAnchor()) return GetAnchor(); - base::stack our_ancestors = GetAncestorAnchors(); - base::stack other_ancestors = other.GetAncestorAnchors(); + base::stack our_ancestors = GetAncestorAnchors(); + base::stack other_ancestors = other.GetAncestorAnchors(); - AXNodeType* common_anchor = nullptr; + AXNode* common_anchor = nullptr; while (!our_ancestors.empty() && !other_ancestors.empty() && our_ancestors.top() == other_ancestors.top()) { common_anchor = our_ancestors.top(); @@ -1121,7 +1085,7 @@ class AXPosition { // See "CreateParentPosition" for an explanation of the use of // |move_direction|. AXPositionInstance CreateAncestorPosition( - const AXNodeType* ancestor_anchor, + const AXNode* ancestor_anchor, ax::mojom::MoveDirection move_direction) const { if (!ancestor_anchor) return CreateNullPosition(); @@ -1147,7 +1111,7 @@ class AXPosition { if (!position->GetAnchor()) return CreateNullPosition(); - if (AXNodeType* empty_object_node = GetEmptyObjectAncestorNode()) { + if (const AXNode* empty_object_node = GetEmptyObjectAncestorNode()) { // In this class, (but only on certain platforms), we define the empty // node as a leaf node (see `AXNode::IsLeaf()`) that doesn't have any // content. So that such nodes will act as a character and a word @@ -1166,7 +1130,7 @@ class AXPosition { // from the descendant to the empty leaf node itself. Otherwise, // character and word navigation won't work properly. return CreateTreePosition( - position->tree_id(), GetAnchorID(empty_object_node), + position->tree_id(), empty_object_node->id(), position->child_index() == BEFORE_TEXT ? BEFORE_TEXT : 0); } @@ -1183,7 +1147,7 @@ class AXPosition { if (!position->GetAnchor()) return CreateNullPosition(); - if (AXNodeType* empty_object_node = GetEmptyObjectAncestorNode()) { + if (const AXNode* empty_object_node = GetEmptyObjectAncestorNode()) { // This is needed because an empty object as defined in this class and // on certain platforms can have descendants that should not be // exposed. See comment above in similar implementation for @@ -1194,7 +1158,7 @@ class AXPosition { // is `AXNode::kEmbeddedCharacterLength`. If the invalid position was // already at the start of the node, we set it to 0. return CreateTextPosition( - position->tree_id(), GetAnchorID(empty_object_node), + position->tree_id(), empty_object_node->id(), position->text_offset() > 0 ? AXNode::kEmbeddedCharacterLength : 0, ax::mojom::TextAffinity::kDownstream); @@ -2029,9 +1993,15 @@ class AXPosition { AXTreeID tree_id = AXTreeIDUnknown(); AXNodeID child_id = kInvalidAXNodeID; - AnchorChild(child_index, &tree_id, &child_id); + const AXNode* child_anchor = + GetAnchor()->GetChildAtCrossingTreeBoundary(child_index); + if (!child_anchor) + return CreateNullPosition(); + tree_id = child_anchor->tree()->GetAXTreeID(); + child_id = child_anchor->id(); DCHECK_NE(tree_id, AXTreeIDUnknown()); DCHECK_NE(child_id, kInvalidAXNodeID); + switch (kind_) { case AXPositionKind::NULL_POSITION: NOTREACHED(); @@ -2082,11 +2052,15 @@ class AXPosition { if (IsNullPosition()) return CreateNullPosition(); - AXTreeID tree_id = AXTreeIDUnknown(); - AXNodeID parent_id = kInvalidAXNodeID; - AnchorParent(&tree_id, &parent_id); - if (tree_id == AXTreeIDUnknown() || parent_id == kInvalidAXNodeID) + AXTreeID parent_tree_id = AXTreeIDUnknown(); + AXNodeID parent_anchor_id = kInvalidAXNodeID; + const AXNode* parent_anchor = GetAnchor()->GetParentCrossingTreeBoundary(); + if (!parent_anchor) return CreateNullPosition(); + parent_tree_id = parent_anchor->tree()->GetAXTreeID(); + parent_anchor_id = parent_anchor->id(); + DCHECK_NE(parent_tree_id, AXTreeIDUnknown()); + DCHECK_NE(parent_anchor_id, kInvalidAXNodeID); switch (kind_) { case AXPositionKind::NULL_POSITION: @@ -2100,7 +2074,8 @@ class AXPosition { // position anchored at the next child, depending on whether this is the // last child in its parent anchor. if (AtEndOfAnchor()) - return CreateTreePosition(tree_id, parent_id, (child_index + 1)); + return CreateTreePosition(parent_tree_id, parent_anchor_id, + (child_index + 1)); switch (move_direction) { case ax::mojom::MoveDirection::kNone: @@ -2117,7 +2092,8 @@ class AXPosition { // "AnchorIndexInParent" always returns a child index that is before // any "object replacement character" in our parent, we use that for // both situations. - return CreateTreePosition(tree_id, parent_id, child_index); + return CreateTreePosition(parent_tree_id, parent_anchor_id, + child_index); case ax::mojom::MoveDirection::kForward: // "move_direction" is only important when this position is an // "embedded object in parent", i.e., when this position's anchor is @@ -2129,7 +2105,8 @@ class AXPosition { // "AnchorIndexInParent" for the child index. if (!AtStartOfAnchor() && IsEmbeddedObjectInParent()) ++child_index; - return CreateTreePosition(tree_id, parent_id, child_index); + return CreateTreePosition(parent_tree_id, parent_anchor_id, + child_index); } } @@ -2248,7 +2225,7 @@ class AXPosition { // breaks, which would create false positives. AXPositionInstance parent_position = CreateTextPosition( - tree_id, parent_id, parent_offset, parent_affinity); + parent_tree_id, parent_anchor_id, parent_offset, parent_affinity); if (AtEndOfAnchor() && !parent_position->AtStartOfAnchor() && !parent_position->AtEndOfAnchor() && parent_position->AtStartOfLine()) { @@ -2257,8 +2234,6 @@ class AXPosition { return parent_position; } } - - return CreateNullPosition(); } // Creates a tree position using the next text-only node as its anchor. @@ -2485,7 +2460,7 @@ class AXPosition { // rooted at this position's anchor. This is necessary because we don't want // to return a position that might be in the shadow DOM when this position // is not. - const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this); + const AXNode* common_anchor = text_position->LowestCommonAnchor(*this); if (GetAnchor() == common_anchor) { text_position = text_position->CreateAncestorPosition( common_anchor, ax::mojom::MoveDirection::kForward); @@ -2559,7 +2534,7 @@ class AXPosition { // rooted at this position's anchor. This is necessary because we don't want // to return a position that might be in the shadow DOM when this position // is not. - const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this); + const AXNode* common_anchor = text_position->LowestCommonAnchor(*this); if (GetAnchor() == common_anchor) { text_position = text_position->CreateAncestorPosition( common_anchor, ax::mojom::MoveDirection::kBackward); @@ -2708,7 +2683,7 @@ class AXPosition { // at the current position. // This is necessary because we don't want to return any position that might // be in the shadow DOM if the original position was not. - const AXNodeType* common_anchor = tree_position->LowestCommonAnchor(*this); + const AXNode* common_anchor = tree_position->LowestCommonAnchor(*this); if (GetAnchor() == common_anchor) { tree_position = tree_position->CreateAncestorPosition( common_anchor, ax::mojom::MoveDirection::kBackward); @@ -2780,7 +2755,7 @@ class AXPosition { // rooted at the current position. // This is necessary because we don't want to return any position that might // be in the shadow DOM if the original position was not. - const AXNodeType* common_anchor = tree_position->LowestCommonAnchor(*this); + const AXNode* common_anchor = tree_position->LowestCommonAnchor(*this); if (GetAnchor() == common_anchor) { tree_position = tree_position->CreateAncestorPosition( common_anchor, ax::mojom::MoveDirection::kForward); @@ -3014,7 +2989,7 @@ class AXPosition { // If the boundary is in the same subtree, return a position rooted at this // position's anchor. This is necessary because we don't want to return a // position that might be in the shadow DOM when this position is not. - const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this); + const AXNode* common_anchor = text_position->LowestCommonAnchor(*this); if (GetAnchor() == common_anchor) { text_position = text_position->CreateAncestorPosition(common_anchor, move_direction); @@ -3155,7 +3130,7 @@ class AXPosition { // If the boundary is in the same subtree, return a position rooted at this // position's anchor. This is necessary because we don't want to return a // position that might be in the shadow DOM when this position is not. - const AXNodeType* common_anchor = text_position->LowestCommonAnchor(*this); + const AXNode* common_anchor = text_position->LowestCommonAnchor(*this); if (GetAnchor() == common_anchor) { text_position = text_position->CreateAncestorPosition(common_anchor, move_direction); @@ -3300,10 +3275,10 @@ class AXPosition { // rather than calling `LowestCommonAnchor`. That way, we can discover the // first uncommon ancestors which we need to use in order to compare the two // positions. - const AXNodeType* common_anchor = nullptr; - base::stack our_ancestors = + const AXNode* common_anchor = nullptr; + base::stack our_ancestors = normalized_this_position->GetAncestorAnchors(); - base::stack other_ancestors = + base::stack other_ancestors = normalized_other_position->GetAncestorAnchors(); while (!our_ancestors.empty() && !other_ancestors.empty() && our_ancestors.top() == other_ancestors.top()) { @@ -3336,13 +3311,13 @@ class AXPosition { return SlowCompareTo(other); AXPositionInstance this_uncommon_tree_position = - CreateTreePosition(GetTreeID(our_ancestors.top()), - GetAnchorID(our_ancestors.top()), 0 /*child_index*/); + CreateTreePosition(our_ancestors.top()->tree()->GetAXTreeID(), + our_ancestors.top()->id(), 0 /*child_index*/); int this_uncommon_ancestor_index = this_uncommon_tree_position->AnchorIndexInParent(); - AXPositionInstance other_uncommon_tree_position = CreateTreePosition( - GetTreeID(other_ancestors.top()), GetAnchorID(other_ancestors.top()), - 0 /*child_index*/); + AXPositionInstance other_uncommon_tree_position = + CreateTreePosition(other_ancestors.top()->tree()->GetAXTreeID(), + other_ancestors.top()->id(), 0 /*child_index*/); int other_uncommon_ancestor_index = other_uncommon_tree_position->AnchorIndexInParent(); DCHECK_NE(this_uncommon_ancestor_index, other_uncommon_ancestor_index) @@ -3485,7 +3460,7 @@ class AXPosition { // position of the other. In all other cases, no information will be lost // when converting to tree positions. - const AXNodeType* common_anchor = this->LowestCommonAnchor(other); + const AXNode* common_anchor = this->LowestCommonAnchor(other); if (!common_anchor) return base::nullopt; @@ -3776,7 +3751,7 @@ class AXPosition { !IsIframe(GetAnchorRole()); } - AXNodeType* GetEmptyObjectAncestorNode() const { + AXNode* GetEmptyObjectAncestorNode() const { if (g_ax_embedded_object_behavior == AXEmbeddedObjectBehavior::kSuppressCharacter || !GetAnchor()) { @@ -3788,7 +3763,7 @@ class AXPosition { // is when we are inside of a collapsed popup button which is the parent // of a menu list popup, or inside a generic container that is the child // of an empty text field. - if (AXNodeType* popup_button = + if (AXNode* popup_button = GetAnchor()->GetCollapsedMenuListPopUpButtonAncestor()) { return popup_button; } @@ -3803,13 +3778,13 @@ class AXPosition { // The first unignored ancestor is necessarily the empty object if this node // is the descendant of an empty object. - AXNodeType* ancestor_node = GetLowestUnignoredAncestor(); + AXNode* ancestor_node = GetLowestUnignoredAncestor(); if (!ancestor_node) return nullptr; - AXPositionInstance position = CreateTextPosition( - tree_id_, GetAnchorID(ancestor_node), 0 /* text_offset */, - ax::mojom::TextAffinity::kDownstream); + AXPositionInstance position = + CreateTextPosition(tree_id_, ancestor_node->id(), 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); if (position && position->IsEmptyObjectReplacedByCharacter()) return ancestor_node; @@ -3824,19 +3799,17 @@ class AXPosition { std::swap(text_offset_, other.text_offset_); std::swap(affinity_, other.affinity_); // We explicitly don't swap any cached members. - name_ = base::string16(); - other.name_ = base::string16(); + name_ = std::u16string(); + other.name_ = std::u16string(); } - // Abstract methods. - // Returns the text (in UTF16 format) that is present inside the anchor node, // including any text found in descendant text nodes, based on the platform's // text representation. Some platforms use an embedded object replacement // character that replaces the text coming from most child nodes. - base::string16 GetText() const { + std::u16string GetText() const { if (IsNullPosition()) - return base::string16(); + return std::u16string(); // Special case, if a position's anchor node has only ignored descendants, // i.e., it appears to be empty to assistive software, on some platforms we @@ -3847,21 +3820,11 @@ class AXPosition { if (IsEmptyObjectReplacedByCharacter()) return AXNode::kEmbeddedCharacter; - // Special case, if a position's anchor node is hosting another - // accessibility tree, return the text that is found in that tree's root. - const AXNode* anchor = GetAnchor(); - const AXTreeManager* child_tree_manager = - AXTreeManagerMap::GetInstance().GetManagerForChildTree(*anchor); - if (child_tree_manager) { - // The child node exists in a separate tree from its parent. - anchor = child_tree_manager->GetRootAsAXNode(); - } - switch (g_ax_embedded_object_behavior) { case AXEmbeddedObjectBehavior::kSuppressCharacter: - return base::UTF8ToUTF16(anchor->GetInnerText()); + return base::UTF8ToUTF16(GetAnchor()->GetInnerText()); case AXEmbeddedObjectBehavior::kExposeCharacter: - return anchor->GetHypertext(); + return GetAnchor()->GetHypertext(); } } @@ -3910,23 +3873,13 @@ class AXPosition { if (IsEmptyObjectReplacedByCharacter()) return AXNode::kEmbeddedCharacterLength; - // Special case, if a position's anchor node is hosting another - // accessibility tree, return the text that is found in that tree's root. - const AXNode* anchor = GetAnchor(); - const AXTreeManager* child_tree_manager = - AXTreeManagerMap::GetInstance().GetManagerForChildTree(*anchor); - if (child_tree_manager) { - // The child node exists in a separate tree from its parent. - anchor = child_tree_manager->GetRootAsAXNode(); - } - switch (g_ax_embedded_object_behavior) { case AXEmbeddedObjectBehavior::kSuppressCharacter: // TODO(nektar): Switch to anchor->GetInnerTextLength() after AXPosition // switches to using UTF8. - return int{base::UTF8ToUTF16(anchor->GetInnerText()).length()}; + return int{base::UTF8ToUTF16(GetAnchor()->GetInnerText()).length()}; case AXEmbeddedObjectBehavior::kExposeCharacter: - return int{anchor->GetHypertext().length()}; + return int{GetAnchor()->GetHypertext().length()}; } } @@ -4034,42 +3987,10 @@ class AXPosition { } } - // Abstract methods. - void AnchorChild(int child_index, - AXTreeID* tree_id, - AXNodeID* child_id) const { - DCHECK(tree_id); - DCHECK(child_id); - if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) { - *tree_id = AXTreeIDUnknown(); - *child_id = kInvalidAXNodeID; - return; - } - - AXNode* child = nullptr; - const AXTreeManager* child_tree_manager = - AXTreeManagerMap::GetInstance().GetManagerForChildTree(*GetAnchor()); - if (child_tree_manager) { - // The child node exists in a separate tree from its parent. - child = child_tree_manager->GetRootAsAXNode(); - *tree_id = child_tree_manager->GetTreeID(); - } else { - child = GetAnchor()->children()[size_t{child_index}]; - *tree_id = this->tree_id(); - } - *child_id = child->id(); - } - int AnchorChildCount() const { if (!GetAnchor()) return 0; - - const AXTreeManager* child_tree_manager = - AXTreeManagerMap::GetInstance().GetManagerForChildTree(*GetAnchor()); - if (child_tree_manager) - return 1; - - return int{GetAnchor()->children().size()}; + return int{GetAnchor()->GetChildCountCrossingTreeBoundary()}; } // When a child is ignored, it looks for unignored nodes of that child's @@ -4083,17 +4004,7 @@ class AXPosition { int AnchorUnignoredChildCount() const { if (!GetAnchor()) return 0; - - const AXTreeManager* child_tree_manager = - AXTreeManagerMap::GetInstance().GetManagerForChildTree(*GetAnchor()); - if (child_tree_manager) { - DCHECK_EQ(GetAnchor()->GetUnignoredChildCount(), 0u) - << "A node cannot be hosting both a child tree and other nodes as " - "children."; - return 1; // A child tree is never ignored. - } - - return int{GetAnchor()->GetUnignoredChildCount()}; + return int{GetAnchor()->GetUnignoredChildCountCrossingTreeBoundary()}; } int AnchorIndexInParent() const { @@ -4101,71 +4012,38 @@ class AXPosition { return GetAnchor() ? int{GetAnchor()->index_in_parent()} : INVALID_INDEX; } - base::stack GetAncestorAnchors() const { + base::stack GetAncestorAnchors() const { if (!GetAnchor()) return base::stack(); base::stack anchors; AXNode* current_anchor = GetAnchor(); - AXNodeID current_anchor_id = GetAnchor()->id(); - AXTreeID current_tree_id = tree_id(); - AXNodeID parent_anchor_id = kInvalidAXNodeID; - AXTreeID parent_tree_id = AXTreeIDUnknown(); - while (current_anchor) { anchors.push(current_anchor); - current_anchor = GetParent( - current_anchor /*child*/, current_tree_id /*child_tree_id*/, - &parent_tree_id /*parent_tree_id*/, &parent_anchor_id /*parent_id*/); - - current_anchor_id = parent_anchor_id; - current_tree_id = parent_tree_id; + // TODO(nektar): Introduce `AXNode::GetParent()` in order to be able to + // cross tree boundaries and remove + // `AXNode::GetUnignoredParentCrossingTreeBoundaries`. + current_anchor = current_anchor->GetParentCrossingTreeBoundary(); } + return anchors; } - AXNodeType* GetLowestUnignoredAncestor() const { + AXNode* GetLowestUnignoredAncestor() const { if (!GetAnchor()) return nullptr; return GetAnchor()->GetLowestPlatformAncestor(); } - void AnchorParent(AXTreeID* tree_id, AXNodeID* parent_id) const { - DCHECK(tree_id); - DCHECK(parent_id); - *tree_id = AXTreeIDUnknown(); - *parent_id = kInvalidAXNodeID; - if (!GetAnchor()) - return; - - GetParent(GetAnchor() /*child*/, this->tree_id() /*child_tree_id*/, - tree_id /*parent_tree_id*/, parent_id /*parent_id*/); - } - - AXNodeType* GetNodeInTree(AXTreeID tree_id, AXNodeData::AXID node_id) const { - if (node_id == kInvalidAXNodeID) - return nullptr; - - AXTreeManager* manager = - AXTreeManagerMap::GetInstance().GetManager(tree_id); - if (manager) - return manager->GetNodeFromTree(tree_id, node_id); - - return nullptr; - } - - AXNodeData::AXID GetAnchorID(AXNodeType* node) const { return node->id(); } - - AXTreeID GetTreeID(AXNodeType* node) const { - return node->tree()->GetAXTreeID(); - } - // Returns the length of text (in UTF16 code points) that this anchor node // takes up in its parent. // // On some platforms, embedded objects are represented in their parent with a // single "embedded object character". int MaxTextOffsetInParent() const { + if (IsNullPosition()) + return 0; + // Ignored anchors are not visible to platform APIs. As a result, their // inner text or hypertext does not appear in their parent node, but the // text of their unignored children does, if any. (See @@ -4237,7 +4115,7 @@ class AXPosition { return GetRole(GetAnchor()); } - ax::mojom::Role GetRole(AXNodeType* node) const { return node->data().role; } + ax::mojom::Role GetRole(AXNode* node) const { return node->data().role; } AXNodeTextStyles GetTextStyles() const { // Check either the current anchor or its parent for text styles. @@ -4288,30 +4166,30 @@ class AXPosition { ax::mojom::IntListAttribute::kWordEnds); } - AXNodeData::AXID GetNextOnLineID(AXNodeData::AXID node_id) const { + AXNodeID GetNextOnLineID() const { if (IsNullPosition()) return kInvalidAXNodeID; - AXNode* node = GetNodeInTree(tree_id(), node_id); + DCHECK(GetAnchor()); + int next_on_line_id; - if (!node || - !node->data().GetIntAttribute(ax::mojom::IntAttribute::kNextOnLineId, - &next_on_line_id)) { - return kInvalidAXNodeID; + if (GetAnchor()->data().GetIntAttribute( + ax::mojom::IntAttribute::kNextOnLineId, &next_on_line_id)) { + return static_cast(next_on_line_id); } - return static_cast(next_on_line_id); + return kInvalidAXNodeID; } - AXNodeData::AXID GetPreviousOnLineID(AXNodeData::AXID node_id) const { + AXNodeID GetPreviousOnLineID() const { if (IsNullPosition()) return kInvalidAXNodeID; - AXNode* node = GetNodeInTree(tree_id(), node_id); + DCHECK(GetAnchor()); + int previous_on_line_id; - if (!node || - !node->data().GetIntAttribute( + if (GetAnchor()->data().GetIntAttribute( ax::mojom::IntAttribute::kPreviousOnLineId, &previous_on_line_id)) { - return kInvalidAXNodeID; + return static_cast(previous_on_line_id); } - return static_cast(previous_on_line_id); + return kInvalidAXNodeID; } private: @@ -5095,7 +4973,7 @@ class AXPosition { // In the case of a leaf position, its inner text (in UTF16 format). Used for // initializing a grapheme break iterator. - mutable base::string16 name_; + mutable std::u16string name_; }; template diff --git a/chromium/ui/accessibility/ax_range.h b/chromium/ui/accessibility/ax_range.h index 0376ee7829d..948907beaca 100644 --- a/chromium/ui/accessibility/ax_range.h +++ b/chromium/ui/accessibility/ax_range.h @@ -11,8 +11,8 @@ #include #include -#include "base/strings/string16.h" #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" @@ -36,6 +36,7 @@ class AXRangeRectDelegate { AXNodeID node_id, int start_offset, int end_offset, + ui::AXClippingBehavior clipping_behavior, AXOffscreenResult* offscreen_result) = 0; virtual gfx::Rect GetBoundsRect(AXTreeID tree_id, AXNodeID node_id, @@ -274,18 +275,18 @@ class AXRange { // Pass a |max_count| of -1 to retrieve all text in the AXRange. // Note that if this AXRange has its anchor or focus located at an ignored // position, we shrink the range to the closest unignored positions. - base::string16 GetText(AXTextConcatenationBehavior concatenation_behavior = + std::u16string GetText(AXTextConcatenationBehavior concatenation_behavior = AXTextConcatenationBehavior::kAsTextContent, int max_count = -1, bool include_ignored = false, size_t* appended_newlines_count = nullptr) const { if (max_count == 0 || IsNull()) - return base::string16(); + return std::u16string(); base::Optional endpoint_comparison = CompareEndpoints(anchor(), focus()); if (!endpoint_comparison) - return base::string16(); + return std::u16string(); AXPositionInstance start = (endpoint_comparison.value() < 0) ? anchor_->AsLeafTextPosition() @@ -294,7 +295,7 @@ class AXRange { ? focus_->AsLeafTextPosition() : anchor_->AsLeafTextPosition(); - base::string16 range_text; + std::u16string range_text; size_t computed_newlines_count = 0; bool is_first_non_whitespace_leaf = true; bool crossed_paragraph_boundary = false; @@ -321,7 +322,7 @@ class AXRange { // When preserving layout line breaks, don't append `\n` next if the // previous leaf position was a
(already ending with a newline). if (crossed_paragraph_boundary && !found_trailing_newline) { - range_text += base::ASCIIToUTF16("\n"); + range_text += u"\n"; computed_newlines_count++; } @@ -376,11 +377,43 @@ class AXRange { std::vector GetRects(AXRangeRectDelegate* delegate) const { std::vector rects; + AXPositionInstance range_start = anchor()->AsLeafTextPosition(); + AXPositionInstance range_end = focus()->AsLeafTextPosition(); + + // For a degenerate range, we want to fetch unclipped bounding rect, because + // text with the same start and end off set (i.e. degenerate) will have an + // inner text bounding rect with height of the character and width of 0, + // which the browser platform will consider as an empty rect and ends up + // clipping it, resulting in size 0x1 rect. + // After we retrieve the unclipped bounding rect, we want to set its width + // to 1 to represent a caret/insertion point. + // + // Note: The caller of this function is only UIA TextPattern, so displaying + // bounding rects for degenerate range is only limited for UIA currently. + if (IsCollapsed() && range_start->IsInTextObject()) { + AXOffscreenResult offscreen_result; + gfx::Rect degenerate_range_rect = delegate->GetInnerTextRangeBoundsRect( + range_start->tree_id(), range_start->anchor_id(), + range_start->text_offset(), range_end->text_offset(), + ui::AXClippingBehavior::kUnclipped, &offscreen_result); + if (offscreen_result == AXOffscreenResult::kOnscreen) { + DCHECK(degenerate_range_rect.width() == 0); + degenerate_range_rect.set_width(1); + rects.push_back(degenerate_range_rect); + } + + return rects; + } + for (const AXRange& leaf_text_range : *this) { DCHECK(leaf_text_range.IsLeafTextRange()); AXPositionType* current_line_start = leaf_text_range.anchor(); AXPositionType* current_line_end = leaf_text_range.focus(); + // We want to skip ranges from ignored nodes. + if (current_line_start->IsIgnored()) + continue; + // For text anchors, we retrieve the bounding rectangles of its text // content. For non-text anchors (such as checkboxes, images, etc.), we // want to directly retrieve their bounding rectangles. @@ -392,7 +425,8 @@ class AXRange { current_line_start->tree_id(), current_line_start->anchor_id(), current_line_start->text_offset(), - current_line_end->text_offset(), &offscreen_result) + current_line_end->text_offset(), + ui::AXClippingBehavior::kClipped, &offscreen_result) : delegate->GetBoundsRect(current_line_start->tree_id(), current_line_start->anchor_id(), &offscreen_result); diff --git a/chromium/ui/accessibility/ax_range_unittest.cc b/chromium/ui/accessibility/ax_range_unittest.cc index 48ac880e7b0..466041ee6b6 100644 --- a/chromium/ui/accessibility/ax_range_unittest.cc +++ b/chromium/ui/accessibility/ax_range_unittest.cc @@ -5,9 +5,9 @@ #include "ui/accessibility/ax_range.h" #include +#include #include -#include "base/strings/string16.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -38,12 +38,15 @@ constexpr AXNodeID TEXT_FIELD_ID = 7; constexpr AXNodeID STATIC_TEXT1_ID = 8; constexpr AXNodeID INLINE_BOX1_ID = 9; constexpr AXNodeID LINE_BREAK1_ID = 10; -constexpr AXNodeID STATIC_TEXT2_ID = 11; -constexpr AXNodeID INLINE_BOX2_ID = 12; -constexpr AXNodeID LINE_BREAK2_ID = 13; -constexpr AXNodeID PARAGRAPH_ID = 14; -constexpr AXNodeID STATIC_TEXT3_ID = 15; -constexpr AXNodeID INLINE_BOX3_ID = 16; +constexpr AXNodeID INLINE_BOX_LINE_BREAK1_ID = 11; +constexpr AXNodeID STATIC_TEXT2_ID = 12; +constexpr AXNodeID INLINE_BOX2_ID = 13; +constexpr AXNodeID LINE_BREAK2_ID = 14; +constexpr AXNodeID INLINE_BOX_LINE_BREAK2_ID = 15; +constexpr AXNodeID PARAGRAPH_ID = 16; +constexpr AXNodeID STATIC_TEXT3_ID = 17; +constexpr AXNodeID INLINE_BOX3_ID = 18; +constexpr AXNodeID EMPTY_PARAGRAPH_ID = 19; class TestAXRangeScreenRectDelegate : public AXRangeRectDelegate { public: @@ -60,6 +63,7 @@ class TestAXRangeScreenRectDelegate : public AXRangeRectDelegate { AXNodeID node_id, int start_offset, int end_offset, + const ui::AXClippingBehavior clipping_behavior, AXOffscreenResult* offscreen_result) override { if (tree_manager_->GetTreeID() != tree_id) return gfx::Rect(); @@ -72,7 +76,7 @@ class TestAXRangeScreenRectDelegate : public AXRangeRectDelegate { TestAXNodeHelper::GetOrCreate(tree_manager_->GetTree(), node); return wrapper->GetInnerTextRangeBoundsRect( start_offset, end_offset, AXCoordinateSystem::kScreenDIPs, - AXClippingBehavior::kClipped, offscreen_result); + clipping_behavior, offscreen_result); } gfx::Rect GetBoundsRect(AXTreeID tree_id, @@ -98,15 +102,15 @@ class TestAXRangeScreenRectDelegate : public AXRangeRectDelegate { class AXRangeTest : public testing::Test, public TestAXTreeManager { public: - const base::string16 EMPTY = base::ASCIIToUTF16(""); - const base::string16 NEWLINE = base::ASCIIToUTF16("\n"); - const base::string16 BUTTON = base::ASCIIToUTF16("Button"); - const base::string16 LINE_1 = base::ASCIIToUTF16("Line 1"); - const base::string16 LINE_2 = base::ASCIIToUTF16("Line 2"); - const base::string16 TEXT_FIELD = + const std::u16string EMPTY = u""; + const std::u16string NEWLINE = u"\n"; + const std::u16string BUTTON = u"Button"; + const std::u16string LINE_1 = u"Line 1"; + const std::u16string LINE_2 = u"Line 2"; + const std::u16string TEXT_FIELD = LINE_1.substr().append(NEWLINE).append(LINE_2).append(NEWLINE); - const base::string16 AFTER_LINE = base::ASCIIToUTF16("After"); - const base::string16 ALL_TEXT = + const std::u16string AFTER_LINE = u"After"; + const std::u16string ALL_TEXT = BUTTON.substr().append(TEXT_FIELD).append(AFTER_LINE); AXRangeTest() = default; @@ -130,13 +134,55 @@ class AXRangeTest : public testing::Test, public TestAXTreeManager { AXNodeData inline_box1_; AXNodeData inline_box2_; AXNodeData inline_box3_; + AXNodeData inline_box_line_break1_; + AXNodeData inline_box_line_break2_; AXNodeData paragraph_; + AXNodeData empty_paragraph_; private: DISALLOW_COPY_AND_ASSIGN(AXRangeTest); }; void AXRangeTest::SetUp() { + // Set up the AXTree for the following content: + // ++1 Role::kDialog + // ++++2 Role::kGenericContainer + // ++++++3 Role::kButton, name="Button" + // ++++++4 Role::kGenericContainer + // ++++++++5 Role::kCheckBox, name="Checkbox 1" + // ++++++++6 Role::kCheckBox, name="Checkbox 2" + // ++++7 Role::kTextField + // ++++++8 Role::kStaticText, name="Line 1" + // ++++++++9 Role::kInlineTextBox, name="Line 1" + // ++++++10 Role::kLineBreak, name="\n" + // ++++++++11 Role::kInlineTextBox, name="\n" + // ++++++12 Role::kStaticText, name="Line 2" + // ++++++++13 Role::kInlineTextBox, name="Line 2" + // ++++++14 Role::kLineBreak, name="\n" + // ++++++++15 Role::kInlineTextBox, name="\n" + // ++++16 Role::kParagraph + // ++++++17 Role::kStaticText, name="After" + // ++++++++18 Role::kInlineTextBox, name="After" + // ++++19 Role::kParagraph, IGNORED + // + // [Root] + // {0, 0, 800, 600} + // + // [Button] [Checkbox 1] [Checkbox 2] + // {20, 20, 100x30}, {120, 20, 30x30} {150, 20, 30x30} + // + // [Line 1] [\n] + // {20, 50, 30x30} {50, 50, 0x30} + // + // [Line 2] [\n] + // {20, 80, 42x30} {62, 80, 0x30} + // + // [After] + // {20, 110, 50x30} + // + // [Empty paragraph] + // {20, 140, 700, 0} + // Most tests use kSuppressCharacter behavior. g_ax_embedded_object_behavior = AXEmbeddedObjectBehavior::kSuppressCharacter; @@ -155,7 +201,10 @@ void AXRangeTest::SetUp() { inline_box1_.id = INLINE_BOX1_ID; inline_box2_.id = INLINE_BOX2_ID; inline_box3_.id = INLINE_BOX3_ID; + inline_box_line_break1_.id = INLINE_BOX_LINE_BREAK1_ID; + inline_box_line_break2_.id = INLINE_BOX_LINE_BREAK2_ID; paragraph_.id = PARAGRAPH_ID; + empty_paragraph_.id = EMPTY_PARAGRAPH_ID; root_.role = ax::mojom::Role::kDialog; root_.AddState(ax::mojom::State::kFocusable); @@ -241,6 +290,19 @@ void AXRangeTest::SetUp() { line_break1_.relative_bounds.bounds = gfx::RectF(50, 50, 0, 30); line_break1_.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId, inline_box1_.id); + line_break1_.child_ids.push_back(inline_box_line_break1_.id); + + inline_box_line_break1_.role = ax::mojom::Role::kInlineTextBox; + inline_box_line_break1_.AddBoolAttribute( + ax::mojom::BoolAttribute::kIsLineBreakingObject, true); + inline_box_line_break1_.SetName(NEWLINE); + inline_box_line_break1_.relative_bounds.bounds = gfx::RectF(50, 50, 0, 30); + inline_box_line_break1_.AddIntListAttribute( + ax::mojom::IntListAttribute::kCharacterOffsets, {0}); + inline_box_line_break1_.AddIntListAttribute( + ax::mojom::IntListAttribute::kWordStarts, std::vector{0}); + inline_box_line_break1_.AddIntListAttribute( + ax::mojom::IntListAttribute::kWordEnds, std::vector{0}); static_text2_.role = ax::mojom::Role::kStaticText; static_text2_.AddState(ax::mojom::State::kEditable); @@ -274,6 +336,19 @@ void AXRangeTest::SetUp() { line_break2_.relative_bounds.bounds = gfx::RectF(62, 80, 0, 30); line_break2_.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId, inline_box2_.id); + line_break2_.child_ids.push_back(inline_box_line_break2_.id); + + inline_box_line_break2_.role = ax::mojom::Role::kInlineTextBox; + inline_box_line_break2_.AddBoolAttribute( + ax::mojom::BoolAttribute::kIsLineBreakingObject, true); + inline_box_line_break2_.SetName(NEWLINE); + inline_box_line_break2_.relative_bounds.bounds = gfx::RectF(62, 80, 0, 30); + inline_box_line_break2_.AddIntListAttribute( + ax::mojom::IntListAttribute::kCharacterOffsets, {0}); + inline_box_line_break2_.AddIntListAttribute( + ax::mojom::IntListAttribute::kWordStarts, std::vector{0}); + inline_box_line_break2_.AddIntListAttribute( + ax::mojom::IntListAttribute::kWordEnds, std::vector{0}); paragraph_.role = ax::mojom::Role::kParagraph; paragraph_.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject, @@ -302,13 +377,32 @@ void AXRangeTest::SetUp() { inline_box3_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, std::vector{5}); + empty_paragraph_.role = ax::mojom::Role::kParagraph; + empty_paragraph_.AddState(ax::mojom::State::kIgnored); + empty_paragraph_.relative_bounds.bounds = gfx::RectF(20, 140, 700, 0); + root_.child_ids.push_back(empty_paragraph_.id); + AXTreeUpdate initial_state; initial_state.root_id = 1; - initial_state.nodes = { - root_, div1_, button_, div2_, - check_box1_, check_box2_, text_field_, static_text1_, - inline_box1_, line_break1_, static_text2_, inline_box2_, - line_break2_, paragraph_, static_text3_, inline_box3_}; + initial_state.nodes = {root_, + div1_, + button_, + div2_, + check_box1_, + check_box2_, + text_field_, + static_text1_, + inline_box1_, + line_break1_, + inline_box_line_break1_, + static_text2_, + inline_box2_, + line_break2_, + inline_box_line_break2_, + paragraph_, + static_text3_, + inline_box3_, + empty_paragraph_}; initial_state.has_tree_data = true; initial_state.tree_data.tree_id = AXTreeID::CreateNewAXTreeID(); initial_state.tree_data.title = "Dialog title"; @@ -547,10 +641,10 @@ TEST_F(AXRangeTest, LeafTextRangeIteration) { ax::mojom::TextAffinity::kDownstream); TestPositionInstance line_break1_start = AXNodePosition::CreateTextPosition( - GetTreeID(), line_break1_.id, 0 /* text_offset */, + GetTreeID(), inline_box_line_break1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); TestPositionInstance line_break1_end = AXNodePosition::CreateTextPosition( - GetTreeID(), line_break1_.id, 1 /* text_offset */, + GetTreeID(), inline_box_line_break1_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); TestPositionInstance line2_start = AXNodePosition::CreateTextPosition( @@ -564,10 +658,10 @@ TEST_F(AXRangeTest, LeafTextRangeIteration) { ax::mojom::TextAffinity::kDownstream); TestPositionInstance line_break2_start = AXNodePosition::CreateTextPosition( - GetTreeID(), line_break2_.id, 0 /* text_offset */, + GetTreeID(), inline_box_line_break2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); TestPositionInstance line_break2_end = AXNodePosition::CreateTextPosition( - GetTreeID(), line_break2_.id, 1 /* text_offset */, + GetTreeID(), inline_box_line_break2_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); TestPositionInstance after_line_start = AXNodePosition::CreateTextPosition( @@ -577,6 +671,14 @@ TEST_F(AXRangeTest, LeafTextRangeIteration) { GetTreeID(), inline_box3_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); + TestPositionInstance empty_paragraph_start = + AXNodePosition::CreateTextPosition(GetTreeID(), empty_paragraph_.id, + 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + TestPositionInstance empty_paragraph_end = AXNodePosition::CreateTextPosition( + GetTreeID(), empty_paragraph_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + std::vector expected_ranges; auto TestRangeIterator = [&expected_ranges](const TestPositionRange& test_range) { @@ -684,6 +786,8 @@ TEST_F(AXRangeTest, LeafTextRangeIteration) { line_break2_end->Clone()); expected_ranges.emplace_back(after_line_start->Clone(), after_line_end->Clone()); + expected_ranges.emplace_back(empty_paragraph_start->Clone(), + empty_paragraph_end->Clone()); TestRangeIterator(entire_test_forward_range); TestRangeIterator(entire_test_backward_range); } @@ -762,7 +866,7 @@ TEST_F(AXRangeTest, GetTextWithWholeObjects) { EXPECT_EQ(LINE_2, static_text2_range_backward.GetText()); // static_text1_ to static_text2_ - base::string16 text_between_text1_start_and_text2_end = + std::u16string text_between_text1_start_and_text2_end = LINE_1.substr().append(NEWLINE).append(LINE_2); start = AXNodePosition::CreateTextPosition( GetTreeID(), static_text1_.id, 0 /* text_offset */, @@ -781,7 +885,7 @@ TEST_F(AXRangeTest, GetTextWithWholeObjects) { static_text_range_backward.GetText()); // root_ to static_text2_'s end - base::string16 text_up_to_text2_end = + std::u16string text_up_to_text2_end = BUTTON.substr(0).append(LINE_1).append(NEWLINE).append(LINE_2); start = AXNodePosition::CreateTreePosition(GetTreeID(), root_.id, 0 /* child_index */); @@ -797,7 +901,7 @@ TEST_F(AXRangeTest, GetTextWithWholeObjects) { root_to_static2_text_range_backward.GetText()); // root_ to static_text2_'s start - base::string16 text_up_to_text2_start = + std::u16string text_up_to_text2_start = BUTTON.substr(0).append(LINE_1).append(NEWLINE); start = AXNodePosition::CreateTreePosition(GetTreeID(), root_.id, 0 /* child_index */); @@ -812,7 +916,7 @@ TEST_F(AXRangeTest, GetTextWithWholeObjects) { } TEST_F(AXRangeTest, GetTextWithTextOffsets) { - base::string16 most_text = BUTTON.substr(2).append(TEXT_FIELD.substr(0, 11)); + std::u16string most_text = BUTTON.substr(2).append(TEXT_FIELD.substr(0, 11)); // Create a range starting from the button object and ending two characters // before the end of the root. TestPositionInstance start = AXNodePosition::CreateTextPosition( @@ -829,7 +933,7 @@ TEST_F(AXRangeTest, GetTextWithTextOffsets) { EXPECT_EQ(most_text, backward_range.GetText()); // root_ to static_text2_'s start with offsets - base::string16 text_up_to_text2_tree_start = + std::u16string text_up_to_text2_tree_start = BUTTON.substr(0).append(TEXT_FIELD.substr(0, 10)); start = AXNodePosition::CreateTreePosition(GetTreeID(), root_.id, 0 /* child_index */); @@ -933,7 +1037,7 @@ TEST_F(AXRangeTest, GetTextAddingNewlineBetweenParagraphs) { auto TestGetTextForRange = [](TestPositionInstance range_start, TestPositionInstance range_end, - const base::string16& expected_text, + const std::u16string& expected_text, const size_t expected_appended_newlines_count) { TestPositionRange forward_test_range(range_start->Clone(), range_end->Clone()); @@ -950,37 +1054,37 @@ TEST_F(AXRangeTest, GetTextAddingNewlineBetweenParagraphs) { EXPECT_EQ(expected_appended_newlines_count, appended_newlines_count); }; - base::string16 button_start_to_line1_end = + std::u16string button_start_to_line1_end = BUTTON.substr().append(NEWLINE).append(LINE_1); TestGetTextForRange(button_start->Clone(), line1_end->Clone(), button_start_to_line1_end, 1); - base::string16 button_start_to_line1_start = BUTTON.substr().append(NEWLINE); + std::u16string button_start_to_line1_start = BUTTON.substr().append(NEWLINE); TestGetTextForRange(button_start->Clone(), line1_start->Clone(), button_start_to_line1_start, 1); - base::string16 button_end_to_line1_end = NEWLINE.substr().append(LINE_1); + std::u16string button_end_to_line1_end = NEWLINE.substr().append(LINE_1); TestGetTextForRange(button_end->Clone(), line1_end->Clone(), button_end_to_line1_end, 1); - base::string16 button_end_to_line1_start = NEWLINE; + std::u16string button_end_to_line1_start = NEWLINE; TestGetTextForRange(button_end->Clone(), line1_start->Clone(), button_end_to_line1_start, 1); - base::string16 line2_start_to_after_line_end = + std::u16string line2_start_to_after_line_end = LINE_2.substr().append(NEWLINE).append(AFTER_LINE); TestGetTextForRange(line2_start->Clone(), after_line_end->Clone(), line2_start_to_after_line_end, 0); - base::string16 line2_start_to_after_line_start = + std::u16string line2_start_to_after_line_start = LINE_2.substr().append(NEWLINE); TestGetTextForRange(line2_start->Clone(), after_line_start->Clone(), line2_start_to_after_line_start, 0); - base::string16 line2_end_to_after_line_end = + std::u16string line2_end_to_after_line_end = NEWLINE.substr().append(AFTER_LINE); TestGetTextForRange(line2_end->Clone(), after_line_end->Clone(), line2_end_to_after_line_end, 0); - base::string16 line2_end_to_after_line_start = NEWLINE; + std::u16string line2_end_to_after_line_start = NEWLINE; TestGetTextForRange(line2_end->Clone(), after_line_start->Clone(), line2_end_to_after_line_start, 0); - base::string16 all_text = + std::u16string all_text = BUTTON.substr().append(NEWLINE).append(TEXT_FIELD).append(AFTER_LINE); TestPositionInstance start = AXNodePosition::CreateTextPosition( GetTreeID(), root_.id, 0 /* text_offset */, @@ -1013,11 +1117,11 @@ TEST_F(AXRangeTest, GetTextWithMaxCount) { } TEST_F(AXRangeTest, GetTextWithList) { - const base::string16 kListMarker1 = base::ASCIIToUTF16("1. "); - const base::string16 kListItemContent = base::ASCIIToUTF16("List item 1"); - const base::string16 kListMarker2 = base::ASCIIToUTF16("2. "); - const base::string16 kAfterList = base::ASCIIToUTF16("After list"); - const base::string16 kAllText = kListMarker1.substr() + const std::u16string kListMarker1 = u"1. "; + const std::u16string kListItemContent = u"List item 1"; + const std::u16string kListMarker2 = u"2. "; + const std::u16string kAfterList = u"After list"; + const std::u16string kAllText = kListMarker1.substr() .append(kListItemContent) .append(NEWLINE) .append(kListMarker2) @@ -1199,8 +1303,8 @@ TEST_F(AXRangeTest, GetRects) { GetTreeID(), inline_box2_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); - TestPositionInstance after_line_end = AXNodePosition::CreateTextPosition( - GetTreeID(), inline_box3_.id, 5 /* text_offset */, + TestPositionInstance empty_paragraph_end = AXNodePosition::CreateTextPosition( + GetTreeID(), empty_paragraph_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); // Since a button is not visible to the text representation, it spans an @@ -1226,6 +1330,16 @@ TEST_F(AXRangeTest, GetRects) { EXPECT_THAT(button_check_box2_range.GetRects(&delegate), testing::ContainerEq(expected_screen_rects)); + // Retrieving bounding box of text line 1's degenerate range at its start. + // 0 1 2 3 4 5 + // |L|i|n|e| |1| + // || + TestPositionRange line1_degenerate_range(line1_start->Clone(), + line1_start->Clone()); + expected_screen_rects = {gfx::Rect(20, 50, 1, 30)}; + EXPECT_THAT(line1_degenerate_range.GetRects(&delegate), + testing::ContainerEq(expected_screen_rects)); + // Retrieving bounding box of text line 1, its whole range. // 0 1 2 3 4 5 // |L|i|n|e| |1| @@ -1304,6 +1418,17 @@ TEST_F(AXRangeTest, GetRects) { EXPECT_THAT(line2_mid_range.GetRects(&delegate), testing::ContainerEq(expected_screen_rects)); + // Retrieving bounding box of degenerate range of text line 2, before its + // second character. + // 0 1 2 3 4 5 + // |L|i|n|e| |2| + // || + TestPositionRange line2_degenerate_range(line2_second_char->Clone(), + 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)); + // 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| // |--------------------------| @@ -1327,7 +1452,7 @@ TEST_F(AXRangeTest, GetRects) { // Retrieving bounding boxes of the range that spans from the checkbox 2 // ("invisible" in the text representation) to the middle of text line 2. - // |[Button][Checkbox 1][Checkbox 2]L|i|n|e| |1|\n|L|i|n|e| |2|\n|A|f|t|e|r| + // |[Button][Checkbox 1][Checkbox 2]L|i|n|e| |1|\n|L|i|n|e| |2|\n|A|f|t|e|r

// |-------------------------------| TestPositionRange check_box2_line2_mid_range(check_box2->Clone(), line2_middle->Clone()); @@ -1338,9 +1463,10 @@ TEST_F(AXRangeTest, GetRects) { 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| - // |-----------------------------------------------------------------------| - TestPositionRange entire_test_range(button->Clone(), after_line_end->Clone()); + // |[Button][Checkbox 1][Checkbox 2]L|i|n|e| |1|\n|L|i|n|e| |2|\n|A|f|t|e|r

+ // |-------------------------------------------------------------------------| + TestPositionRange entire_test_range(button->Clone(), + empty_paragraph_end->Clone()); expected_screen_rects = { gfx::Rect(20, 20, 100, 30), gfx::Rect(120, 20, 30, 30), gfx::Rect(150, 20, 30, 30), gfx::Rect(20, 50, 30, 30), @@ -1363,26 +1489,29 @@ TEST_F(AXRangeTest, GetRectsOffscreen) { GetTreeID(), button_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); - TestPositionInstance after_line_end = AXNodePosition::CreateTextPosition( - GetTreeID(), inline_box3_.id, 5 /* text_offset */, + TestPositionInstance empty_paragraph_end = AXNodePosition::CreateTextPosition( + GetTreeID(), empty_paragraph_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); // [Button] [Checkbox 1] [Checkbox 2] // {20, 20, 100x30}, {120, 20, 30x30} {150, 20, 30x30} // --- - // [Line 1] | + // [Line 1] [\n] | // {20, 50, 30x30} | view port, onscreen // | {0, 50, 800x60} - // [Line 2] | + // [Line 2] [\n] | // {20, 80, 42x30} | // --- // [After] // {20, 110, 50x30} // + // [Empty paragraph] + // // 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| - // |-----------------------------------------------------------------------| - TestPositionRange entire_test_range(button->Clone(), after_line_end->Clone()); + // |[Button][Checkbox 1][Checkbox 2]L|i|n|e| |1|\n|L|i|n|e| |2|\n|A|f|t|e|r

+ // |-------------------------------------------------------------------------| + TestPositionRange entire_test_range(button->Clone(), + empty_paragraph_end->Clone()); std::vector expected_screen_rects = {gfx::Rect(20, 50, 30, 30), gfx::Rect(20, 80, 42, 30)}; EXPECT_THAT(entire_test_range.GetRects(&delegate), diff --git a/chromium/ui/accessibility/ax_role_properties.cc b/chromium/ui/accessibility/ax_role_properties.cc index 95bf0582da8..4f28632978e 100644 --- a/chromium/ui/accessibility/ax_role_properties.cc +++ b/chromium/ui/accessibility/ax_role_properties.cc @@ -192,23 +192,23 @@ bool IsControlOnAndroid(const ax::mojom::Role role, bool isFocusable) { switch (role) { case ax::mojom::Role::kSplitter: return isFocusable; - case ax::mojom::Role::kTreeItem: case ax::mojom::Role::kDate: case ax::mojom::Role::kDateTime: - case ax::mojom::Role::kInputTime: case ax::mojom::Role::kDocBackLink: case ax::mojom::Role::kDocBiblioRef: case ax::mojom::Role::kDocGlossRef: case ax::mojom::Role::kDocNoteRef: + case ax::mojom::Role::kInputTime: case ax::mojom::Role::kLink: + case ax::mojom::Role::kTreeItem: return true; + case ax::mojom::Role::kAlert: + case ax::mojom::Role::kDialog: case ax::mojom::Role::kMenu: case ax::mojom::Role::kMenuBar: case ax::mojom::Role::kNone: - case ax::mojom::Role::kUnknown: case ax::mojom::Role::kTree: - case ax::mojom::Role::kDialog: - case ax::mojom::Role::kAlert: + case ax::mojom::Role::kUnknown: return false; default: return IsControl(role); @@ -280,7 +280,6 @@ bool IsImage(const ax::mojom::Role role) { case ax::mojom::Role::kDocCover: case ax::mojom::Role::kGraphicsSymbol: case ax::mojom::Role::kImage: - case ax::mojom::Role::kImageMap: case ax::mojom::Role::kSvgRoot: return true; default: @@ -754,7 +753,6 @@ bool ShouldHaveReadonlyStateByDefault(const ax::mojom::Role role) { case ax::mojom::Role::kDocument: case ax::mojom::Role::kGraphicsDocument: case ax::mojom::Role::kImage: - case ax::mojom::Role::kImageMap: case ax::mojom::Role::kList: case ax::mojom::Role::kListItem: case ax::mojom::Role::kPdfRoot: diff --git a/chromium/ui/accessibility/ax_table_info.cc b/chromium/ui/accessibility/ax_table_info.cc index 141d844a317..39076ca04ad 100644 --- a/chromium/ui/accessibility/ax_table_info.cc +++ b/chromium/ui/accessibility/ax_table_info.cc @@ -134,8 +134,9 @@ bool AXTableInfo::Update() { // On Mac, we add a few extra nodes to the table - see comment // at the top of UpdateExtraMacNodes for details. - if (tree_->enable_extra_mac_nodes()) - UpdateExtraMacNodes(); +#if defined(AX_EXTRA_MAC_NODES) + UpdateExtraMacNodes(); +#endif // The table metadata is now valid, any table queries will now be // fast. Any time a node in the table is updated, we'll have to diff --git a/chromium/ui/accessibility/ax_table_info.h b/chromium/ui/accessibility/ax_table_info.h index d33dcb6959b..891a15b7027 100644 --- a/chromium/ui/accessibility/ax_table_info.h +++ b/chromium/ui/accessibility/ax_table_info.h @@ -10,6 +10,7 @@ #include #include "base/optional.h" +#include "build/build_config.h" #include "ui/accessibility/ax_export.h" #include "ui/accessibility/ax_node_data.h" @@ -18,6 +19,10 @@ namespace ui { class AXTree; class AXNode; +#if defined(OS_MAC) +#define AX_EXTRA_MAC_NODES 1 +#endif + // This helper class computes info about tables and grids in AXTrees. class AX_EXPORT AXTableInfo { public: diff --git a/chromium/ui/accessibility/ax_table_info_unittest.cc b/chromium/ui/accessibility/ax_table_info_unittest.cc index fc5f07ca114..eacd8763221 100644 --- a/chromium/ui/accessibility/ax_table_info_unittest.cc +++ b/chromium/ui/accessibility/ax_table_info_unittest.cc @@ -5,6 +5,7 @@ #include "ui/accessibility/ax_table_info.h" #include "base/stl_util.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node.h" @@ -160,7 +161,11 @@ TEST_F(AXTableInfoTest, SimpleTable) { EXPECT_EQ(2, table_info->row_nodes[0]->data().id); EXPECT_EQ(3, table_info->row_nodes[1]->data().id); +#if defined(OS_MAC) + EXPECT_EQ(3U, table_info->extra_mac_nodes.size()); +#else EXPECT_EQ(0U, table_info->extra_mac_nodes.size()); +#endif // // High-level: Test the helper functions on AXNode. @@ -492,6 +497,8 @@ TEST_F(AXTableInfoTest, HeadersWithSpans) { EXPECT_EQ(4, table_info->row_nodes[2]->data().id); } +#if defined(OS_MAC) + TEST_F(AXTableInfoTest, ExtraMacNodes) { // Simple 2 x 2 table with 2 column headers in first row, 2 cells in second // row. @@ -510,7 +517,6 @@ TEST_F(AXTableInfoTest, ExtraMacNodes) { MakeCell(&initial_state.nodes[6], 7, 1, 1); AXTree tree(initial_state); - tree.SetEnableExtraMacNodes(true); AXTableInfo* table_info = GetTableInfo(&tree, tree.root()->children()[0]); EXPECT_FALSE(table_info); @@ -570,6 +576,8 @@ TEST_F(AXTableInfoTest, ExtraMacNodes) { EXPECT_EQ(5, indirect_child_ids[1]); } +#endif + TEST_F(AXTableInfoTest, TableWithNoIndices) { AXTreeUpdate initial_state; initial_state.root_id = 1; @@ -937,6 +945,8 @@ TEST_F(AXTableInfoTest, TableChanges) { EXPECT_FALSE(table_info); } +#if defined(OS_MAC) + TEST_F(AXTableInfoTest, ExtraMacNodesChanges) { // Simple 2 x 2 table with 2 column headers in first row, 2 cells in second // row. @@ -955,7 +965,6 @@ TEST_F(AXTableInfoTest, ExtraMacNodesChanges) { MakeCell(&initial_state.nodes[6], 7, 1, 1); AXTree tree(initial_state); - tree.SetEnableExtraMacNodes(true); AXTableInfo* table_info = GetTableInfo(&tree, tree.root()); ASSERT_NE(nullptr, table_info); // We expect 3 extra Mac nodes: two column nodes, and one header node. @@ -1078,6 +1087,8 @@ TEST_F(AXTableInfoTest, ExtraMacNodesChanges) { } } +#endif + TEST_F(AXTableInfoTest, RowColumnSpanChanges) { // Simple 2 col x 1 row table AXTreeUpdate update; diff --git a/chromium/ui/accessibility/ax_text_utils.cc b/chromium/ui/accessibility/ax_text_utils.cc index 3dbfdb4474e..425ff7cfbe5 100644 --- a/chromium/ui/accessibility/ax_text_utils.cc +++ b/chromium/ui/accessibility/ax_text_utils.cc @@ -47,7 +47,7 @@ base::i18n::BreakIterator::BreakType ICUBreakTypeForBoundaryType( // line_breaks is a Misnomer. Blink provides the start offsets of each line // not the line breaks. // TODO(nektar): Rename line_breaks a11y attribute and variable references. -size_t FindAccessibleTextBoundary(const base::string16& text, +size_t FindAccessibleTextBoundary(const std::u16string& text, const std::vector& line_breaks, ax::mojom::TextBoundary boundary, size_t start_offset, @@ -182,7 +182,7 @@ size_t FindAccessibleTextBoundary(const base::string16& text, } } -std::vector GetWordStartOffsets(const base::string16& text) { +std::vector GetWordStartOffsets(const std::u16string& text) { std::vector word_starts; base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); if (!iter.Init()) @@ -197,7 +197,7 @@ std::vector GetWordStartOffsets(const base::string16& text) { return word_starts; } -std::vector GetWordEndOffsets(const base::string16& text) { +std::vector GetWordEndOffsets(const std::u16string& text) { std::vector word_ends; base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); if (!iter.Init()) @@ -211,7 +211,7 @@ std::vector GetWordEndOffsets(const base::string16& text) { return word_ends; } -std::vector GetSentenceStartOffsets(const base::string16& text) { +std::vector GetSentenceStartOffsets(const std::u16string& text) { std::vector sentence_starts; base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_SENTENCE); @@ -225,7 +225,7 @@ std::vector GetSentenceStartOffsets(const base::string16& text) { return sentence_starts; } -std::vector GetSentenceEndOffsets(const base::string16& text) { +std::vector GetSentenceEndOffsets(const std::u16string& text) { std::vector sentence_ends; base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_SENTENCE); diff --git a/chromium/ui/accessibility/ax_text_utils.h b/chromium/ui/accessibility/ax_text_utils.h index f8a9552b642..d233073ee37 100644 --- a/chromium/ui/accessibility/ax_text_utils.h +++ b/chromium/ui/accessibility/ax_text_utils.h @@ -7,9 +7,9 @@ #include +#include #include -#include "base/strings/string16.h" #include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/accessibility/ax_export.h" @@ -20,7 +20,7 @@ namespace ui { // (depending on |direction|) from the given |start_offset| until the // given boundary is found, and return the offset of that boundary, // using the vector of line break character offsets in |line_breaks|. -AX_EXPORT size_t FindAccessibleTextBoundary(const base::string16& text, +AX_EXPORT size_t FindAccessibleTextBoundary(const std::u16string& text, const std::vector& line_breaks, ax::mojom::TextBoundary boundary, size_t start_offset, @@ -28,23 +28,23 @@ AX_EXPORT size_t FindAccessibleTextBoundary(const base::string16& text, ax::mojom::TextAffinity affinity); // Returns a string ID that corresponds to the name of the given action. -AX_EXPORT base::string16 ActionVerbToLocalizedString( +AX_EXPORT std::u16string ActionVerbToLocalizedString( const ax::mojom::DefaultActionVerb action_verb); // Returns the non-localized string representation of a supported action. // Some APIs on Linux and Windows need to return non-localized action names. -AX_EXPORT base::string16 ActionVerbToUnlocalizedString( +AX_EXPORT std::u16string ActionVerbToUnlocalizedString( const ax::mojom::DefaultActionVerb action_verb); // Returns indices of all word starts in |text|. -AX_EXPORT std::vector GetWordStartOffsets(const base::string16& text); +AX_EXPORT std::vector GetWordStartOffsets(const std::u16string& text); // Returns indices of all word ends in |text|. -AX_EXPORT std::vector GetWordEndOffsets(const base::string16& text); +AX_EXPORT std::vector GetWordEndOffsets(const std::u16string& text); // Returns indices of all sentence starts in |text|. -AX_EXPORT std::vector GetSentenceStartOffsets(const base::string16& text); +AX_EXPORT std::vector GetSentenceStartOffsets(const std::u16string& text); // Returns indices of all sentence ends in |text|. -AX_EXPORT std::vector GetSentenceEndOffsets(const base::string16& text); +AX_EXPORT std::vector GetSentenceEndOffsets(const std::u16string& text); } // namespace ui #endif // UI_ACCESSIBILITY_AX_TEXT_UTILS_H_ diff --git a/chromium/ui/accessibility/ax_text_utils_unittest.cc b/chromium/ui/accessibility/ax_text_utils_unittest.cc index 9b8613ffb2e..8fd8a3f7186 100644 --- a/chromium/ui/accessibility/ax_text_utils_unittest.cc +++ b/chromium/ui/accessibility/ax_text_utils_unittest.cc @@ -15,7 +15,7 @@ namespace ui { TEST(AXTextUtils, FindAccessibleTextBoundaryWord) { - const base::string16 text = + const std::u16string text = base::UTF8ToUTF16("Hello there.This/is\ntesting."); const size_t text_length = text.length(); std::vector line_start_offsets; @@ -74,7 +74,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryWord) { } TEST(AXTextUtils, FindAccessibleTextBoundaryLine) { - const base::string16 text = base::UTF8ToUTF16("Line 1.\nLine 2\n\t"); + const std::u16string text = base::UTF8ToUTF16("Line 1.\nLine 2\n\t"); const size_t text_length = text.length(); std::vector line_start_offsets; line_start_offsets.push_back(8); @@ -143,7 +143,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryLine) { } TEST(AXTextUtils, FindAccessibleTextBoundarySentence) { - auto find_sentence_boundaries_at_offset = [](const base::string16& text, + auto find_sentence_boundaries_at_offset = [](const std::u16string& text, int offset) { std::vector line_start_offsets; size_t backwards = FindAccessibleTextBoundary( @@ -157,7 +157,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundarySentence) { return std::make_pair(backwards, forwards); }; - const base::string16 text = + const std::u16string text = base::UTF8ToUTF16("Sentence 1. Sentence 2...\n\tSentence 3! Sentence 4"); std::pair boundaries = find_sentence_boundaries_at_offset(text, 5); @@ -190,7 +190,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundarySentence) { // The sentence should include whitespace all the way until the end of the // string. - const base::string16 text2 = base::UTF8ToUTF16("A sentence . \n\n\t\t\n"); + const std::u16string text2 = base::UTF8ToUTF16("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); @@ -217,8 +217,8 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryCharacter) { L" ", }; - std::vector characters; - base::string16 text; + std::vector characters; + std::u16string text; for (auto*& i : kCharacters) { characters.push_back(base::WideToUTF16(i)); text.append(characters.back()); @@ -266,7 +266,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryCharacter) { } TEST(AXTextUtils, GetWordOffsetsEmptyTest) { - const base::string16 text = base::UTF8ToUTF16(""); + const std::u16string text = u""; std::vector word_starts = GetWordStartOffsets(text); std::vector word_ends = GetWordEndOffsets(text); EXPECT_EQ(0UL, word_starts.size()); @@ -274,41 +274,41 @@ TEST(AXTextUtils, GetWordOffsetsEmptyTest) { } TEST(AXTextUtils, GetWordStartOffsetsBasicTest) { - const base::string16 text = base::UTF8ToUTF16("This is very simple input"); + const std::u16string text = u"This is very simple input"; EXPECT_THAT(GetWordStartOffsets(text), testing::ElementsAre(0, 5, 8, 13, 20)); } TEST(AXTextUtils, GetWordEndOffsetsBasicTest) { - const base::string16 text = base::UTF8ToUTF16("This is very simple input"); + const std::u16string text = u"This is very simple input"; EXPECT_THAT(GetWordEndOffsets(text), testing::ElementsAre(4, 7, 12, 19, 25)); } TEST(AXTextUtils, GetWordStartOffsetsMalformedInputTest) { - const base::string16 text = - base::UTF8ToUTF16("..we *## should parse $#@$ through bad ,, input"); + const std::u16string text = + u"..we *## should parse $#@$ through bad ,, input"; EXPECT_THAT(GetWordStartOffsets(text), testing::ElementsAre(2, 9, 16, 27, 35, 43)); } TEST(AXTextUtils, GetSentenceStartOffsetsBasicTest) { - const base::string16 text = base::UTF8ToUTF16( + const std::u16string text = base::UTF8ToUTF16( "This is the first sentence. This is the second sentence"); EXPECT_THAT(GetSentenceStartOffsets(text), testing::ElementsAre(0, 28)); } TEST(AXTextUtils, GetSentenceEndOffsetsBasicTest) { - const base::string16 text = base::UTF8ToUTF16( + const std::u16string text = base::UTF8ToUTF16( "This is the first sentence. This is the second sentence"); EXPECT_THAT(GetSentenceEndOffsets(text), testing::ElementsAre(28, 55)); } TEST(AXTextUtils, GetSentenceStartOffsetsMalformedInputTest) { - const base::string16 text = base::UTF8ToUTF16("is the first ... second."); + const std::u16string text = u"is the first ... second."; EXPECT_THAT(GetSentenceStartOffsets(text), testing::ElementsAre(0)); } TEST(AXTextUtils, GetSentenceEndOffsetsMalformedInputTest) { - const base::string16 text = base::UTF8ToUTF16("is the first ... second."); + const std::u16string text = u"is the first ... second."; EXPECT_THAT(GetSentenceEndOffsets(text), testing::ElementsAre(24)); } diff --git a/chromium/ui/accessibility/ax_tree.cc b/chromium/ui/accessibility/ax_tree.cc index d8594752bec..b9ac1d26551 100644 --- a/chromium/ui/accessibility/ax_tree.cc +++ b/chromium/ui/accessibility/ax_tree.cc @@ -1054,6 +1054,9 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) { if (!ValidatePendingChangesComplete(update_state)) return false; + std::vector changes; + changes.reserve(update.nodes.size()); + // Look for changes to nodes that are a descendant of a table, // and invalidate their table info if so. We have to walk up the // ancestry of every node that was updated potentially, so keep track of @@ -1066,8 +1069,14 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) { break; // Remove any table infos. const auto& table_info_entry = table_info_map_.find(node->id()); - if (table_info_entry != table_info_map_.end()) + if (table_info_entry != table_info_map_.end()) { table_info_entry->second->Invalidate(); +#if defined(AX_EXTRA_MAC_NODES) + // It will emit children changed notification on mac to make sure that + // extra mac accessibles are recreated. + changes.emplace_back(node, AXTreeObserver::NODE_CHANGED); +#endif + } table_ids_checked.insert(node->id()); node = node->parent(); } @@ -1076,8 +1085,6 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) { // Clears |node_set_size_pos_in_set_info_map_| node_set_size_pos_in_set_info_map_.clear(); - std::vector changes; - changes.reserve(update.nodes.size()); std::set visited_observer_changes; for (size_t i = 0; i < update.nodes.size(); ++i) { AXNode* node = GetFromId(update.nodes[i].id); @@ -1920,19 +1927,6 @@ bool AXTree::CreateNewChildVector(AXNode* node, return success; } -void AXTree::SetEnableExtraMacNodes(bool enabled) { - if (enable_extra_mac_nodes_ == enabled) - return; // No change. - if (enable_extra_mac_nodes_ && !enabled) { - NOTREACHED() - << "We don't support disabling the extra Mac nodes once enabled."; - return; - } - - DCHECK_EQ(0U, table_info_map_.size()); - enable_extra_mac_nodes_ = enabled; -} - AXNodeID AXTree::GetNextNegativeInternalNodeId() { AXNodeID return_value = next_negative_internal_node_id_; next_negative_internal_node_id_--; diff --git a/chromium/ui/accessibility/ax_tree.h b/chromium/ui/accessibility/ax_tree.h index 5d3836eae36..1ff83ecd3b4 100644 --- a/chromium/ui/accessibility/ax_tree.h +++ b/chromium/ui/accessibility/ax_tree.h @@ -166,11 +166,6 @@ class AX_EXPORT AXTree : public AXNode::OwnerTree { int size() { return static_cast(id_map_.size()); } - // Call this to enable support for extra Mac nodes - for each table, - // a table column header and a node for each column. - void SetEnableExtraMacNodes(bool enabled); - bool enable_extra_mac_nodes() const { return enable_extra_mac_nodes_; } - // Return a negative number that's suitable to use for a node ID for // internal nodes created automatically by an AXTree, so as not to // conflict with positive-numbered node IDs from tree sources. @@ -362,12 +357,6 @@ class AX_EXPORT AXTree : public AXNode::OwnerTree { // The next negative node ID to use for internal nodes. AXNodeID next_negative_internal_node_id_ = -1; - // Whether we should create extra nodes that - // are only useful on macOS. Implemented using this flag to allow - // this code to be unit-tested on other platforms (for example, more - // code sanitizers run on Linux). - bool enable_extra_mac_nodes_ = false; - // Contains pos_in_set and set_size data for an AXNode. struct NodeSetSizePosInSetInfo { NodeSetSizePosInSetInfo(); diff --git a/chromium/ui/accessibility/ax_tree_combiner.h b/chromium/ui/accessibility/ax_tree_combiner.h index 3fc2b88d846..b3ee96ea185 100644 --- a/chromium/ui/accessibility/ax_tree_combiner.h +++ b/chromium/ui/accessibility/ax_tree_combiner.h @@ -7,8 +7,8 @@ #include +#include "ui/accessibility/ax_action_handler_registry.h" #include "ui/accessibility/ax_export.h" -#include "ui/accessibility/ax_tree_id_registry.h" #include "ui/accessibility/ax_tree_update.h" namespace ui { diff --git a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc index 0bf8893aae5..36889a7d350 100644 --- a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc +++ b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc @@ -55,8 +55,7 @@ TEST(CombineAXTreesTest, EmbedChildTree) { parent_tree.nodes[1].role = ax::mojom::Role::kButton; parent_tree.nodes[2].id = 3; parent_tree.nodes[2].role = ax::mojom::Role::kIframe; - parent_tree.nodes[2].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_2.ToString()); + parent_tree.nodes[2].AddChildTreeId(tree_id_2); AXTreeUpdate child_tree; child_tree.root_id = 1; @@ -181,8 +180,7 @@ TEST(CombineAXTreesTest, FocusedTree) { parent_tree.nodes[1].role = ax::mojom::Role::kButton; parent_tree.nodes[2].id = 3; parent_tree.nodes[2].role = ax::mojom::Role::kIframe; - parent_tree.nodes[2].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_2.ToString()); + parent_tree.nodes[2].AddChildTreeId(tree_id_2); AXTreeUpdate child_tree; child_tree.has_tree_data = true; diff --git a/chromium/ui/accessibility/ax_tree_data.h b/chromium/ui/accessibility/ax_tree_data.h index e8800b092c4..66bbaee13ac 100644 --- a/chromium/ui/accessibility/ax_tree_data.h +++ b/chromium/ui/accessibility/ax_tree_data.h @@ -12,12 +12,11 @@ #include #include "base/optional.h" -#include "base/strings/string16.h" #include "base/strings/string_split.h" +#include "ui/accessibility/ax_action_handler_registry.h" #include "ui/accessibility/ax_base_export.h" #include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/accessibility/ax_node_data.h" -#include "ui/accessibility/ax_tree_id_registry.h" #include "ui/gfx/geometry/rect.h" namespace ui { diff --git a/chromium/ui/accessibility/ax_tree_id.cc b/chromium/ui/accessibility/ax_tree_id.cc index d829f43da91..d7f8877f6b3 100644 --- a/chromium/ui/accessibility/ax_tree_id.cc +++ b/chromium/ui/accessibility/ax_tree_id.cc @@ -44,7 +44,10 @@ AXTreeID AXTreeID::FromString(const std::string& string) { // static AXTreeID AXTreeID::FromToken(const base::UnguessableToken& token) { - return AXTreeID(token.ToString()); + AXTreeID id; + id.type_ = ax::mojom::AXTreeIDType::kToken; + id.token_ = token; + return id; } // static diff --git a/chromium/ui/accessibility/ax_tree_id_registry.cc b/chromium/ui/accessibility/ax_tree_id_registry.cc deleted file mode 100644 index ca706c3d6a2..00000000000 --- a/chromium/ui/accessibility/ax_tree_id_registry.cc +++ /dev/null @@ -1,87 +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/accessibility/ax_tree_id_registry.h" - -#include "base/memory/singleton.h" -#include "base/strings/string_number_conversions.h" -#include "ui/accessibility/ax_action_handler_base.h" - -namespace ui { - -// static -AXTreeIDRegistry* AXTreeIDRegistry::GetInstance() { - return base::Singleton::get(); -} - -void AXTreeIDRegistry::SetFrameIDForAXTreeID(const FrameID& frame_id, - const AXTreeID& ax_tree_id) { - auto it = frame_to_ax_tree_id_map_.find(frame_id); - if (it != frame_to_ax_tree_id_map_.end()) { - NOTREACHED(); - return; - } - - frame_to_ax_tree_id_map_[frame_id] = ax_tree_id; - ax_tree_to_frame_id_map_[ax_tree_id] = frame_id; -} - -AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID( - const AXTreeID& ax_tree_id) { - auto it = ax_tree_to_frame_id_map_.find(ax_tree_id); - if (it != ax_tree_to_frame_id_map_.end()) - return it->second; - - return FrameID(-1, -1); -} - -AXTreeID AXTreeIDRegistry::GetAXTreeID(AXTreeIDRegistry::FrameID frame_id) { - auto it = frame_to_ax_tree_id_map_.find(frame_id); - if (it != frame_to_ax_tree_id_map_.end()) - return it->second; - - return ui::AXTreeIDUnknown(); -} - -AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(AXActionHandlerBase* handler) { - for (auto it : id_to_action_handler_) { - if (it.second == handler) - return it.first; - } - AXTreeID new_id = AXTreeID::CreateNewAXTreeID(); - SetAXTreeID(new_id, handler); - return new_id; -} - -AXActionHandlerBase* AXTreeIDRegistry::GetActionHandler(AXTreeID ax_tree_id) { - auto it = id_to_action_handler_.find(ax_tree_id); - if (it == id_to_action_handler_.end()) - return nullptr; - return it->second; -} - -void AXTreeIDRegistry::SetAXTreeID(const ui::AXTreeID& id, - AXActionHandlerBase* action_handler) { - DCHECK(id_to_action_handler_.find(id) == id_to_action_handler_.end()); - id_to_action_handler_[id] = action_handler; -} - -void AXTreeIDRegistry::RemoveAXTreeID(AXTreeID ax_tree_id) { - auto frame_it = ax_tree_to_frame_id_map_.find(ax_tree_id); - if (frame_it != ax_tree_to_frame_id_map_.end()) { - frame_to_ax_tree_id_map_.erase(frame_it->second); - ax_tree_to_frame_id_map_.erase(frame_it); - } - - auto action_it = id_to_action_handler_.find(ax_tree_id); - if (action_it != id_to_action_handler_.end()) - id_to_action_handler_.erase(action_it); -} - -AXTreeIDRegistry::AXTreeIDRegistry() { -} - -AXTreeIDRegistry::~AXTreeIDRegistry() {} - -} // namespace ui diff --git a/chromium/ui/accessibility/ax_tree_id_registry.h b/chromium/ui/accessibility/ax_tree_id_registry.h deleted file mode 100644 index f597ed6fd37..00000000000 --- a/chromium/ui/accessibility/ax_tree_id_registry.h +++ /dev/null @@ -1,87 +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. - -#ifndef UI_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_ -#define UI_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_ - -#include -#include -#include - -#include "base/macros.h" -#include "ui/accessibility/ax_action_handler.h" -#include "ui/accessibility/ax_base_export.h" -#include "ui/accessibility/ax_tree_id.h" - -namespace base { -template -struct DefaultSingletonTraits; -} // namespace base - -namespace ui { - -class AXActionHandlerBase; - -// This class generates and saves a runtime id for an accessibility tree. -// It provides a few distinct forms of generating an id: -// - from a frame id (which consists of a process and routing id) -// - from a backing |AXActionHandlerBase| object -// -// The first form allows underlying instances to change but refer to the same -// frame. -// The second form allows this registry to track the object for later retrieval. -class AX_BASE_EXPORT AXTreeIDRegistry { - public: - using FrameID = std::pair; - - // Get the single instance of this class. - static AXTreeIDRegistry* GetInstance(); - - // Gets the frame id based on an ax tree id. - FrameID GetFrameID(const AXTreeID& ax_tree_id); - - // Gets an ax tree id from a frame id. - AXTreeID GetAXTreeID(FrameID frame_id); - - // Retrieve an |AXActionHandlerBase| based on an ax tree id. - AXActionHandlerBase* GetActionHandler(AXTreeID ax_tree_id); - - // Removes an ax tree id, and its associated delegate and frame id (if it - // exists). - void RemoveAXTreeID(AXTreeID ax_tree_id); - - // Associate a frame id with an ax tree id. - void SetFrameIDForAXTreeID(const FrameID& frame_id, - const AXTreeID& ax_tree_id); - - private: - friend struct base::DefaultSingletonTraits; - friend AXActionHandler; - friend AXActionHandlerBase; - - // Get or create a ax tree id keyed on |handler|. - AXTreeID GetOrCreateAXTreeID(AXActionHandlerBase* handler); - - // Set a mapping between an AXTreeID and AXActionHandlerBase explicitly. - void SetAXTreeID(const AXTreeID& ax_tree_id, - AXActionHandlerBase* action_handler); - - AXTreeIDRegistry(); - virtual ~AXTreeIDRegistry(); - - // Maps an accessibility tree to its frame via ids. - std::map ax_tree_to_frame_id_map_; - - // Maps frames to an accessibility tree via ids. - std::map frame_to_ax_tree_id_map_; - - // Maps an id to its handler. - std::map id_to_action_handler_; - - DISALLOW_COPY_AND_ASSIGN(AXTreeIDRegistry); -}; - -} // namespace ui - -#endif // UI_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_ diff --git a/chromium/ui/accessibility/ax_tree_id_unittest.cc b/chromium/ui/accessibility/ax_tree_id_unittest.cc new file mode 100644 index 00000000000..380183283be --- /dev/null +++ b/chromium/ui/accessibility/ax_tree_id_unittest.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/accessibility/ax_tree_id.h" + +#include "base/unguessable_token.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ui { + +TEST(AXTreeIDTest, ToStringFromString) { + AXTreeID tree_id = AXTreeID::CreateNewAXTreeID(); + AXTreeID new_tree_id = AXTreeID::FromString(tree_id.ToString()); + ASSERT_EQ(tree_id, new_tree_id); +} + +TEST(AXTreeIDTest, ToTokenFromToken) { + AXTreeID tree_id = AXTreeID::CreateNewAXTreeID(); + AXTreeID new_tree_id = AXTreeID::FromToken(tree_id.token().value()); + ASSERT_EQ(tree_id, new_tree_id); +} + +} // namespace ui diff --git a/chromium/ui/accessibility/ax_tree_unittest.cc b/chromium/ui/accessibility/ax_tree_unittest.cc index 22f87bfafa2..e169e7d50ea 100644 --- a/chromium/ui/accessibility/ax_tree_unittest.cc +++ b/chromium/ui/accessibility/ax_tree_unittest.cc @@ -3114,14 +3114,11 @@ TEST(AXTreeTest, ChildTreeIds) { initial_state.nodes[0].child_ids.push_back(3); initial_state.nodes[0].child_ids.push_back(4); initial_state.nodes[1].id = 2; - initial_state.nodes[1].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_2.ToString()); + initial_state.nodes[1].AddChildTreeId(tree_id_2); initial_state.nodes[2].id = 3; - initial_state.nodes[2].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_3.ToString()); + initial_state.nodes[2].AddChildTreeId(tree_id_3); initial_state.nodes[3].id = 4; - initial_state.nodes[3].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_3.ToString()); + initial_state.nodes[3].AddChildTreeId(tree_id_3); AXTree tree(initial_state); auto child_tree_1_nodes = tree.GetNodeIdsForChildTreeId(tree_id_1); @@ -3138,8 +3135,7 @@ TEST(AXTreeTest, ChildTreeIds) { AXTreeUpdate update = initial_state; update.nodes[2].string_attributes.clear(); - update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - tree_id_2.ToString()); + update.nodes[2].AddChildTreeId(tree_id_2); update.nodes[3].string_attributes.clear(); EXPECT_TRUE(tree.Unserialize(update)); diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb index bdfcc4295fe..f038f65423c 100644 --- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb +++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb @@ -3,7 +3,7 @@ કાળા પર પીળો તેમની વૈકલ્પિક ટેક્સ્ટ સાથે છબીઓ બદલાવો. -એનિમેશન નીતિ: +ઍનિમેશન પૉલિસી: વાદળી સામાન્ય બધા છબી એનિમેશન બંધ કરો. @@ -62,7 +62,7 @@ aria-describedat અથવા longdesc લક્ષણો દ્વારા ઘટકો પર કિનારી ઉમેરો. લાલ કૅરેટ બ્રાઉઝિંગ વિકલ્પો -એનિમેશન નીતિ +ઍનિમેશન પૉલિસી ઉચ્ચ કોન્ટ્રાસ્ટ કૅરેટ બ્રાઉઝિંગ ચાલુ કરવા માટે <span class='key'>F7</span> દબાવો. તેને બંધ કરવા માટે તેને ફરીથી દબાવો. સંદર્ભ મેનુમાં લાંબા વર્ણનો diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ne.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ne.xtb index 1625ac72dfa..223dd8fae6e 100644 --- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ne.xtb +++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ne.xtb @@ -22,7 +22,7 @@ सेटअप गर्नुहोस् साइट आफू अनुकूल बिर्सनुहोस् सक्षम बनाउनुहोस् -पूर्वनिर्धारित योजनाका रूपमा स्थापना गर्नुहोस् +डिफल्ट योजनाका रूपमा स्थापना गर्नुहोस् छवि वैकल्पिक पाठ दर्शक यसको लामो वर्णन पहुँच गर्न "longdesc" वा "aria-describedat" विशेषता कुनै पनि चीजमा दायाँ-क्लिक गर्नुहोस्। बाँण कुञ्जी प्रयोग गरी वेब पृष्ठका पाठ ब्राउज गर्नुहोस्। @@ -41,7 +41,7 @@ उच्च कन्ट्रास्ट अक्षम गरिएको छ किबोर्ड आदेशहरू एनिमेसन एक पटक मात्र सञ्चालन गर्नुहोस्, एनिमेसन पूर्ण रूपमा असक्षम गर्नुहोस्। -पूर्वनिर्धारित रङ्ग योजना: +डिफल्ट रङ्ग योजना: दृश्य प्रतिक्रिया वेब पृष्ठहरू पढ्न थप सजिलो पार्न रङ्ग योजना परिवर्तन गर्नुहोस् वा उल्टाउनुहोस्। रिसेट गर्नुहोस् 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 16d8d009d3e..ee1814268f2 100644 --- a/chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h +++ b/chromium/ui/accessibility/mojom/ax_assistant_structure_mojom_traits.h @@ -42,7 +42,7 @@ struct StructTraits& node) { return node->rect; } - static base::string16 text(const std::unique_ptr& node) { + static std::u16string text(const std::unique_ptr& node) { return node->text; } static float text_size(const std::unique_ptr& node) { diff --git a/chromium/ui/accessibility/platform/BUILD.gn b/chromium/ui/accessibility/platform/BUILD.gn index c65c091356d..5533603bb95 100644 --- a/chromium/ui/accessibility/platform/BUILD.gn +++ b/chromium/ui/accessibility/platform/BUILD.gn @@ -63,6 +63,8 @@ source_set("platform") { "inspect/ax_event_recorder.h", "inspect/ax_inspect.cc", "inspect/ax_inspect.h", + "inspect/ax_inspect_scenario.cc", + "inspect/ax_inspect_scenario.h", "inspect/ax_property_node.cc", "inspect/ax_property_node.h", "inspect/ax_tree_formatter.cc", @@ -157,10 +159,6 @@ source_set("platform") { if (use_glib) { configs += [ "//build/config/linux:glib" ] } - - if (use_x11) { - public_deps += [ "//ui/gfx/x" ] - } } } } diff --git a/chromium/ui/accessibility/platform/ax_android_constants.cc b/chromium/ui/accessibility/platform/ax_android_constants.cc index 926818cc483..71b7c356ffb 100644 --- a/chromium/ui/accessibility/platform/ax_android_constants.cc +++ b/chromium/ui/accessibility/platform/ax_android_constants.cc @@ -38,6 +38,6 @@ const char kAXToggleButtonClassname[] = "android.widget.ToggleButton"; const char kAXViewClassname[] = "android.view.View"; const char kAXViewGroupClassname[] = "android.view.ViewGroup"; const char kAXWebViewClassname[] = "android.webkit.WebView"; -const base::char16 kSecurePasswordBullet = 0x2022; +const char16_t kSecurePasswordBullet = 0x2022; } // namespace ui diff --git a/chromium/ui/accessibility/platform/ax_android_constants.h b/chromium/ui/accessibility/platform/ax_android_constants.h index 6892b280f9a..fe83123b0f1 100644 --- a/chromium/ui/accessibility/platform/ax_android_constants.h +++ b/chromium/ui/accessibility/platform/ax_android_constants.h @@ -5,7 +5,8 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_AX_ANDROID_CONSTANTS_H_ #define UI_ACCESSIBILITY_PLATFORM_AX_ANDROID_CONSTANTS_H_ -#include "base/strings/string16.h" +#include + #include "ui/accessibility/ax_export.h" namespace ui { @@ -41,7 +42,7 @@ AX_EXPORT extern const char kAXToggleButtonClassname[]; AX_EXPORT extern const char kAXViewClassname[]; AX_EXPORT extern const char kAXViewGroupClassname[]; AX_EXPORT extern const char kAXWebViewClassname[]; -AX_EXPORT extern const base::char16 kSecurePasswordBullet; +AX_EXPORT extern const char16_t kSecurePasswordBullet; } // namespace ui diff --git a/chromium/ui/accessibility/platform/ax_platform_node.h b/chromium/ui/accessibility/platform/ax_platform_node.h index e8ad7edc608..82fe33607d3 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node.h +++ b/chromium/ui/accessibility/platform/ax_platform_node.h @@ -83,7 +83,7 @@ class AX_EXPORT AXPlatformNode { #if defined(OS_APPLE) // Fire a platform-specific notification to announce |text|. - virtual void AnnounceText(const base::string16& text) = 0; + virtual void AnnounceText(const std::u16string& text) = 0; #endif // Return this object's delegate. diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc index b1d16d65633..b68c9ca3b10 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc @@ -970,7 +970,7 @@ gchar* GetText(AtkText* atk_text, gint start_offset, gint end_offset) { if (!obj) return nullptr; - base::string16 text = obj->GetHypertext(); + std::u16string text = obj->GetHypertext(); start_offset = obj->UnicodeToUTF16OffsetInText(start_offset); if (start_offset < 0 || start_offset >= static_cast(text.size())) @@ -1012,7 +1012,7 @@ gunichar GetCharacterAtOffset(AtkText* atk_text, int offset) { if (!obj) return 0; - base::string16 text = obj->GetHypertext(); + std::u16string text = obj->GetHypertext(); int32_t text_length = text.length(); offset = obj->UnicodeToUTF16OffsetInText(offset); @@ -1103,10 +1103,10 @@ char* GetTextWithBoundaryType(AtkText* atk_text, *start_offset_ptr = obj->UTF16ToUnicodeOffsetInText(start_offset); *end_offset_ptr = obj->UTF16ToUnicodeOffsetInText(end_offset); - base::string16 text = obj->GetHypertext(); + std::u16string text = obj->GetHypertext(); DCHECK_LE(end_offset, static_cast(text.size())); - base::string16 substr = text.substr(start_offset, end_offset - start_offset); + std::u16string substr = text.substr(start_offset, end_offset - start_offset); return g_strdup(base::UTF16ToUTF8(substr).c_str()); } @@ -2803,9 +2803,7 @@ AtkRole AXPlatformNodeAuraLinux::GetAtkRole() const { case ax::mojom::Role::kIgnored: return ATK_ROLE_REDUNDANT_OBJECT; case ax::mojom::Role::kImage: - return ATK_ROLE_IMAGE; - case ax::mojom::Role::kImageMap: - return ATK_ROLE_IMAGE_MAP; + return IsImageWithMap() ? ATK_ROLE_IMAGE_MAP : ATK_ROLE_IMAGE; case ax::mojom::Role::kInlineTextBox: return kStaticRole; case ax::mojom::Role::kInputTime: @@ -4186,7 +4184,7 @@ void AXPlatformNodeAuraLinux::UpdateHypertext() { ComputeHypertextRemovedAndInserted(old_hypertext, &shared_prefix, &old_len, &new_len); if (old_len > 0) { - base::string16 removed_substring = + std::u16string removed_substring = old_hypertext.hypertext.substr(shared_prefix, old_len); size_t shared_unicode_prefix = shared_prefix; @@ -4202,7 +4200,7 @@ void AXPlatformNodeAuraLinux::UpdateHypertext() { } if (new_len > 0) { - base::string16 inserted_substring = + std::u16string inserted_substring = hypertext_.hypertext.substr(shared_prefix, new_len); size_t shared_unicode_prefix = UTF16ToUnicodeOffsetInText(shared_prefix); size_t shared_unicode_suffix = @@ -4226,7 +4224,7 @@ AXPlatformNodeAuraLinux::GetHypertextAdjustments() { text_unicode_adjustments_.emplace(); - base::string16 text = GetHypertext(); + std::u16string text = GetHypertext(); int32_t text_length = text.size(); for (int32_t i = 0; i < text_length; i++) { uint32_t code_point; @@ -4661,7 +4659,7 @@ bool AXPlatformNodeAuraLinux::SetTextSelectionForAtkText(int start_offset, start_offset = UnicodeToUTF16OffsetInText(start_offset); end_offset = UnicodeToUTF16OffsetInText(end_offset); - base::string16 text = GetHypertext(); + std::u16string text = GetHypertext(); if (start_offset < 0 || start_offset > int{text.length()}) return false; if (end_offset < 0 || end_offset > int{text.length()}) @@ -4846,7 +4844,7 @@ AXPlatformNodeAuraLinux::GetUnclippedHypertextRangeBoundsRect(int start_offset, start_offset = UnicodeToUTF16OffsetInText(start_offset); end_offset = UnicodeToUTF16OffsetInText(end_offset); - base::string16 text = GetHypertext(); + std::u16string text = GetHypertext(); if (start_offset < 0 || start_offset > int{text.length()}) return base::nullopt; if (end_offset < 0 || end_offset > int{text.length()}) diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h index 493fcfdcbb3..431e1c77a6f 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h @@ -310,10 +310,6 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase { PlatformAttributeList* attributes) override; private: - using AXPositionInstance = AXNodePosition::AXPositionInstance; - using AXPositionInstanceType = typename AXPositionInstance::element_type; - using AXNodeRange = AXRange; - // This is static to ensure that we aren't trying to access the rest of the // accessibility tree during node initialization. static ImplementedAtkInterfaces GetGTypeInterfaceMask(const AXNodeData& data); diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.cc b/chromium/ui/accessibility/platform/ax_platform_node_base.cc index 9d256299be8..d6000f02540 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_base.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_base.cc @@ -63,8 +63,7 @@ bool FindDescendantRoleWithMaxDepth(AXPlatformNodeBase* node, } // namespace -const base::char16 AXPlatformNodeBase::kEmbeddedCharacter = - STRING16_LITERAL('\xfffc'); +const char16_t AXPlatformNodeBase::kEmbeddedCharacter = u'\xfffc'; // Map from each AXPlatformNode's unique id to its instance. using UniqueIdMap = std::unordered_map; @@ -313,7 +312,7 @@ void AXPlatformNodeBase::NotifyAccessibilityEvent(ax::mojom::Event event_type) { } #if defined(OS_APPLE) -void AXPlatformNodeBase::AnnounceText(const base::string16& text) {} +void AXPlatformNodeBase::AnnounceText(const std::u16string& text) {} #endif AXPlatformNodeDelegate* AXPlatformNodeBase::GetDelegate() const { @@ -468,16 +467,16 @@ bool AXPlatformNodeBase::GetStringAttribute( return GetData().GetStringAttribute(attribute, value); } -base::string16 AXPlatformNodeBase::GetString16Attribute( +std::u16string AXPlatformNodeBase::GetString16Attribute( ax::mojom::StringAttribute attribute) const { if (!delegate_) - return base::string16(); + return std::u16string(); return GetData().GetString16Attribute(attribute); } bool AXPlatformNodeBase::GetString16Attribute( ax::mojom::StringAttribute attribute, - base::string16* value) const { + std::u16string* value) const { if (!delegate_) return false; return GetData().GetString16Attribute(attribute, value); @@ -521,7 +520,7 @@ const std::string& AXPlatformNodeBase::GetInheritedStringAttribute( return base::EmptyString(); } -base::string16 AXPlatformNodeBase::GetInheritedString16Attribute( +std::u16string AXPlatformNodeBase::GetInheritedString16Attribute( ax::mojom::StringAttribute attribute) const { return base::UTF8ToUTF16(GetInheritedStringAttribute(attribute)); } @@ -548,7 +547,7 @@ bool AXPlatformNodeBase::GetInheritedStringAttribute( bool AXPlatformNodeBase::GetInheritedString16Attribute( ax::mojom::StringAttribute attribute, - base::string16* value) const { + std::u16string* value) const { std::string value_utf8; if (!GetInheritedStringAttribute(attribute, &value_utf8)) return false; @@ -657,9 +656,9 @@ bool AXPlatformNodeBase::IsText() const { return delegate_ && delegate_->IsText(); } -base::string16 AXPlatformNodeBase::GetHypertext() const { +std::u16string AXPlatformNodeBase::GetHypertext() const { if (!delegate_) - return base::string16(); + return std::u16string(); // Hypertext of platform leaves, which internally are composite objects, are // represented with the inner text of the internal composite object. These @@ -672,13 +671,13 @@ base::string16 AXPlatformNodeBase::GetHypertext() const { return hypertext_.hypertext; } -base::string16 AXPlatformNodeBase::GetInnerText() const { +std::u16string AXPlatformNodeBase::GetInnerText() const { if (!delegate_) - return base::string16(); + return std::u16string(); return delegate_->GetInnerText(); } -base::string16 +std::u16string AXPlatformNodeBase::GetRoleDescriptionFromImageAnnotationStatusOrFromAttribute() const { if (GetData().role == ax::mojom::Role::kImage && @@ -692,8 +691,8 @@ AXPlatformNodeBase::GetRoleDescriptionFromImageAnnotationStatusOrFromAttribute() return GetString16Attribute(ax::mojom::StringAttribute::kRoleDescription); } -base::string16 AXPlatformNodeBase::GetRoleDescription() const { - base::string16 role_description = +std::u16string AXPlatformNodeBase::GetRoleDescription() const { + std::u16string role_description = GetRoleDescriptionFromImageAnnotationStatusOrFromAttribute(); if (!role_description.empty()) { @@ -703,6 +702,12 @@ base::string16 AXPlatformNodeBase::GetRoleDescription() const { return GetDelegate()->GetLocalizedStringForRoleDescription(); } +bool AXPlatformNodeBase::IsImageWithMap() const { + DCHECK_EQ(GetData().role, ax::mojom::Role::kImage) + << "Only call IsImageWithMap() on an image"; + return GetChildCount(); +} + AXPlatformNodeBase* AXPlatformNodeBase::GetSelectionContainer() const { if (!delegate_) return nullptr; @@ -957,9 +962,9 @@ bool AXPlatformNodeBase::IsVerticallyScrollable() const { GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax); } -base::string16 AXPlatformNodeBase::GetValueForControl() const { +std::u16string AXPlatformNodeBase::GetValueForControl() const { if (!delegate_) - return base::string16(); + return std::u16string(); return delegate_->GetValueForControl(); } @@ -986,7 +991,7 @@ void AXPlatformNodeBase::ComputeAttributes(PlatformAttributeList* attributes) { AddAttributeToList("autocomplete", "list", attributes); } - base::string16 role_description = + std::u16string role_description = GetRoleDescriptionFromImageAnnotationStatusOrFromAttribute(); if (!role_description.empty() || HasStringAttribute(ax::mojom::StringAttribute::kRoleDescription)) { @@ -1345,7 +1350,7 @@ void AXPlatformNodeBase::UpdateComputedHypertext() const { // embedded object character for all the other children. Build up a map from // the character index of each embedded object character to the id of the // child object it points to. - base::string16 hypertext; + std::u16string hypertext; for (AXPlatformNodeChildIterator child_iter = AXPlatformNodeChildrenBegin(); child_iter != AXPlatformNodeChildrenEnd(); ++child_iter) { // Similar to Firefox, we don't expose text nodes in IAccessible2 and ATK @@ -1737,8 +1742,8 @@ bool AXPlatformNodeBase::IsSameHypertextCharacter( // For anything other than the "embedded character", we just compare the // characters directly. - base::char16 old_ch = old_hypertext.hypertext[old_char_index]; - base::char16 new_ch = hypertext_.hypertext[new_char_index]; + char16_t old_ch = old_hypertext.hypertext[old_char_index]; + char16_t new_ch = hypertext_.hypertext[new_char_index]; if (old_ch != new_ch) return false; if (new_ch != kEmbeddedCharacter) @@ -1770,7 +1775,7 @@ bool AXPlatformNodeBase::IsSameHypertextCharacter( } // Return true if the index represents a text character. -bool AXPlatformNodeBase::IsText(const base::string16& text, +bool AXPlatformNodeBase::IsText(const std::u16string& text, size_t index, bool is_indexed_from_end) { size_t text_len = text.size(); @@ -1799,8 +1804,8 @@ void AXPlatformNodeBase::ComputeHypertextRemovedAndInserted( if (IsText()) return; - const base::string16& old_text = old_hypertext.hypertext; - const base::string16& new_text = hypertext_.hypertext; + const std::u16string& old_text = old_hypertext.hypertext; + const std::u16string& new_text = hypertext_.hypertext; // TODO(accessibility) Plumb through which part of text changed so we don't // have to guess what changed based on character differences. This can be diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.h b/chromium/ui/accessibility/platform/ax_platform_node_base.h index f8e7dccdd2a..b89c1237c45 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_base.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_base.h @@ -52,7 +52,7 @@ struct AX_EXPORT AXHypertext { // Hypertext. std::vector hyperlinks; - base::string16 hypertext; + std::u16string hypertext; }; class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode { @@ -93,7 +93,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode { void NotifyAccessibilityEvent(ax::mojom::Event event_type) override; #if defined(OS_APPLE) - void AnnounceText(const base::string16& text) override; + void AnnounceText(const std::u16string& text) override; #endif AXPlatformNodeDelegate* GetDelegate() const override; @@ -133,18 +133,18 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode { bool GetStringAttribute(ax::mojom::StringAttribute attribute, std::string* value) const; bool GetString16Attribute(ax::mojom::StringAttribute attribute, - base::string16* value) const; - base::string16 GetString16Attribute( + std::u16string* value) const; + std::u16string GetString16Attribute( ax::mojom::StringAttribute attribute) const; bool HasInheritedStringAttribute(ax::mojom::StringAttribute attribute) const; const std::string& GetInheritedStringAttribute( ax::mojom::StringAttribute attribute) const; - base::string16 GetInheritedString16Attribute( + std::u16string GetInheritedString16Attribute( ax::mojom::StringAttribute attribute) const; bool GetInheritedStringAttribute(ax::mojom::StringAttribute attribute, std::string* value) const; bool GetInheritedString16Attribute(ax::mojom::StringAttribute attribute, - base::string16* value) const; + std::u16string* value) const; bool HasIntListAttribute(ax::mojom::IntListAttribute attribute) const; const std::vector& GetIntListAttribute( @@ -280,7 +280,7 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode { // object character", and every textual child node with its visible accessible // name. This is how displayed text and embedded objects are represented in // ATK and IA2 APIs. - base::string16 GetHypertext() const; + std::u16string GetHypertext() const; // Returns the text that is found inside this node and all its descendants; // including text found in embedded objects. @@ -288,20 +288,20 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode { // Only text displayed on screen is included. Text from ARIA and HTML // attributes that is either not displayed on screen, or outside this node, // e.g. aria-label and HTML title, is not returned. - base::string16 GetInnerText() const; + std::u16string GetInnerText() const; // Returns the value of a control such as a text field, a slider, a // element, a date picker or an ARIA combo box. In order to minimize // cross-process communication between the renderer and the browser, may // compute the value from the control's inner text in the case of a text // field. - virtual base::string16 GetValueForControl() const = 0; + virtual std::u16string GetValueForControl() const = 0; // Get the unignored selection from the tree, meaning the selection whose // endpoints are on unignored nodes. (An ignored node means that the node @@ -211,7 +211,7 @@ class AX_EXPORT AXPlatformNodeDelegate { // Returns the text of this node and represent the text of descendant nodes // with a special character in place of every embedded object. This represents // the concept of text in ATK and IA2 APIs. - virtual base::string16 GetHypertext() const = 0; + virtual std::u16string GetHypertext() const = 0; // Set the selection in the hypertext of this node. Depending on the // implementation, this may mean the new selection will span multiple nodes. @@ -338,7 +338,7 @@ class AX_EXPORT AXPlatformNodeDelegate { // any instance of the application, regardless of locale. The author ID should // be unique among sibling accessibility nodes and is best if unique across // the application, however, not meeting this requirement is non-fatal. - virtual base::string16 GetAuthorUniqueId() const = 0; + virtual std::u16string GetAuthorUniqueId() const = 0; virtual const AXUniqueId& GetUniqueId() const = 0; @@ -441,13 +441,13 @@ class AX_EXPORT AXPlatformNodeDelegate { // Localized strings. // - virtual base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() + virtual std::u16string GetLocalizedRoleDescriptionForUnlabeledImage() const = 0; - virtual base::string16 GetLocalizedStringForImageAnnotationStatus( + virtual std::u16string GetLocalizedStringForImageAnnotationStatus( ax::mojom::ImageAnnotationStatus status) const = 0; - virtual base::string16 GetLocalizedStringForLandmarkType() const = 0; - virtual base::string16 GetLocalizedStringForRoleDescription() const = 0; - virtual base::string16 GetStyleNameAttributeAsLocalizedString() const = 0; + virtual std::u16string GetLocalizedStringForLandmarkType() const = 0; + virtual std::u16string GetLocalizedStringForRoleDescription() const = 0; + virtual std::u16string GetStyleNameAttributeAsLocalizedString() const = 0; // // Testing. 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 cbc3c5ce561..0a1a0c1759b 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc @@ -31,14 +31,14 @@ const AXTreeData& AXPlatformNodeDelegateBase::GetTreeData() const { return *empty_data; } -base::string16 AXPlatformNodeDelegateBase::GetInnerText() const { +std::u16string AXPlatformNodeDelegateBase::GetInnerText() const { // Unlike in web content The "kValue" attribute always takes precedence, // because we assume that users of this base class, such as Views controls, // are carefully crafted by hand, in contrast to HTML pages, where any content // that might be present in the shadow DOM (AKA in the internal accessibility // tree) is actually used by the renderer when assigning the "kValue" // attribute, including any redundant white space. - base::string16 value = + std::u16string value = GetData().GetString16Attribute(ax::mojom::StringAttribute::kValue); if (!value.empty()) return value; @@ -50,7 +50,7 @@ base::string16 AXPlatformNodeDelegateBase::GetInnerText() const { if (IsLeaf() && !GetData().IsInvisibleOrIgnored()) return GetData().GetString16Attribute(ax::mojom::StringAttribute::kName); - base::string16 inner_text; + std::u16string inner_text; for (int i = 0; i < GetChildCount(); ++i) { // TODO(nektar): Add const to all tree traversal methods and remove // const_cast. @@ -63,11 +63,11 @@ base::string16 AXPlatformNodeDelegateBase::GetInnerText() const { return inner_text; } -base::string16 AXPlatformNodeDelegateBase::GetValueForControl() const { +std::u16string AXPlatformNodeDelegateBase::GetValueForControl() const { if (!IsControl(GetData().role) && !GetData().IsRangeValueSupported()) - return base::string16(); + return std::u16string(); - base::string16 value = + std::u16string value = GetData().GetString16Attribute(ax::mojom::StringAttribute::kValue); float numeric_value; if (GetData().IsRangeValueSupported() && value.empty() && @@ -293,8 +293,8 @@ std::string AXPlatformNodeDelegateBase::GetName() const { return GetData().GetStringAttribute(ax::mojom::StringAttribute::kName); } -base::string16 AXPlatformNodeDelegateBase::GetHypertext() const { - return base::string16(); +std::u16string AXPlatformNodeDelegateBase::GetHypertext() const { + return std::u16string(); } bool AXPlatformNodeDelegateBase::SetHypertextSelection(int start_offset, @@ -547,31 +547,31 @@ bool AXPlatformNodeDelegateBase::AccessibilityPerformAction( return false; } -base::string16 +std::u16string AXPlatformNodeDelegateBase::GetLocalizedStringForImageAnnotationStatus( ax::mojom::ImageAnnotationStatus status) const { - return base::string16(); + return std::u16string(); } -base::string16 +std::u16string AXPlatformNodeDelegateBase::GetLocalizedRoleDescriptionForUnlabeledImage() const { - return base::string16(); + return std::u16string(); } -base::string16 AXPlatformNodeDelegateBase::GetLocalizedStringForLandmarkType() +std::u16string AXPlatformNodeDelegateBase::GetLocalizedStringForLandmarkType() const { - return base::string16(); + return std::u16string(); } -base::string16 +std::u16string AXPlatformNodeDelegateBase::GetLocalizedStringForRoleDescription() const { - return base::string16(); + return std::u16string(); } -base::string16 +std::u16string AXPlatformNodeDelegateBase::GetStyleNameAttributeAsLocalizedString() const { - return base::string16(); + return std::u16string(); } TextAttributeMap AXPlatformNodeDelegateBase::ComputeTextAttributeMap( @@ -671,8 +671,8 @@ std::set AXPlatformNodeDelegateBase::GetReverseRelations( return std::set(); } -base::string16 AXPlatformNodeDelegateBase::GetAuthorUniqueId() const { - return base::string16(); +std::u16string AXPlatformNodeDelegateBase::GetAuthorUniqueId() const { + return std::u16string(); } const AXUniqueId& AXPlatformNodeDelegateBase::GetUniqueId() const { 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 46f1e9a3222..c15e3eb2cd0 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.h @@ -35,8 +35,8 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate { // Get the accessibility tree data for this node. const AXTreeData& GetTreeData() const override; - base::string16 GetInnerText() const override; - base::string16 GetValueForControl() const override; + std::u16string GetInnerText() const override; + std::u16string GetValueForControl() const override; const AXTree::Selection GetUnignoredSelection() const override; // Creates a text position rooted at this object. @@ -103,7 +103,7 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate { std::unique_ptr ChildrenEnd() override; std::string GetName() const override; - base::string16 GetHypertext() const override; + std::u16string GetHypertext() const override; bool SetHypertextSelection(int start_offset, int end_offset) override; TextAttributeMap ComputeTextAttributeMap( const TextAttributeList& default_attributes) const override; @@ -201,7 +201,7 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate { std::set GetReverseRelations( ax::mojom::IntListAttribute attr) override; - base::string16 GetAuthorUniqueId() const override; + std::u16string GetAuthorUniqueId() const override; const AXUniqueId& GetUniqueId() const override; @@ -284,12 +284,12 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate { // Localized strings. // - base::string16 GetLocalizedStringForImageAnnotationStatus( + std::u16string GetLocalizedStringForImageAnnotationStatus( ax::mojom::ImageAnnotationStatus status) const override; - base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() const override; - base::string16 GetLocalizedStringForLandmarkType() const override; - base::string16 GetLocalizedStringForRoleDescription() const override; - base::string16 GetStyleNameAttributeAsLocalizedString() const override; + std::u16string GetLocalizedRoleDescriptionForUnlabeledImage() const override; + std::u16string GetLocalizedStringForLandmarkType() const override; + std::u16string GetLocalizedStringForRoleDescription() const override; + std::u16string GetStyleNameAttributeAsLocalizedString() const override; // // Testing. diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.h b/chromium/ui/accessibility/platform/ax_platform_node_mac.h index c28d1a9fdc5..0bb391c7926 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_mac.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.h @@ -23,7 +23,7 @@ class AXPlatformNodeMac : public AXPlatformNodeBase { // AXPlatformNode. gfx::NativeViewAccessible GetNativeViewAccessible() override; void NotifyAccessibilityEvent(ax::mojom::Event event_type) override; - void AnnounceText(const base::string16& text) override; + void AnnounceText(const std::u16string& text) override; // AXPlatformNodeBase. void Destroy() override; diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm index 3ef8956d61f..3fabf9995c8 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm @@ -142,7 +142,6 @@ RoleMap BuildRoleMap() { {ax::mojom::Role::kIframePresentational, NSAccessibilityGroupRole}, {ax::mojom::Role::kIgnored, NSAccessibilityUnknownRole}, {ax::mojom::Role::kImage, NSAccessibilityImageRole}, - {ax::mojom::Role::kImageMap, NSAccessibilityGroupRole}, {ax::mojom::Role::kInputTime, @"AXTimeField"}, {ax::mojom::Role::kLabelText, NSAccessibilityGroupRole}, {ax::mojom::Role::kLayoutTable, NSAccessibilityGroupRole}, @@ -1293,7 +1292,7 @@ void AXPlatformNodeMac::NotifyAccessibilityEvent(ax::mojom::Event event_type) { NotifyMacEvent(native_node_, event_type); } -void AXPlatformNodeMac::AnnounceText(const base::string16& text) { +void AXPlatformNodeMac::AnnounceText(const std::u16string& text) { PostAnnouncementNotification(base::SysUTF16ToNSString(text), [native_node_ AXWindow], false); } 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 60bb50c0395..4e0c8742d09 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 @@ -271,9 +271,8 @@ TEST_F(AXPlatformNodeTextChildProviderTest, base::win::ScopedBstr text_content; EXPECT_HRESULT_SUCCEEDED( text_range_provider->GetText(-1, text_content.Receive())); - EXPECT_EQ( - base::WideToUTF16(text_content.Get()), - kEmbeddedCharacterAsString + STRING16_LITERAL("text child of nontext.")); + EXPECT_EQ(base::WideToUTF16(text_content.Get()), + kEmbeddedCharacterAsString + u"text child of nontext."); ComPtr enclosing_element; text_range_provider->GetEnclosingElement(&enclosing_element); diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.cc index 71b3a8847ad..17ba4a2214b 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.cc @@ -323,6 +323,19 @@ ITextRangeProvider* AXPlatformNodeTextProviderWin::GetRangeFromChild( ancestor, std::move(start), std::move(end)); } +ITextRangeProvider* AXPlatformNodeTextProviderWin::CreateDegenerateRangeAtStart( + ui::AXPlatformNodeWin* node) { + DCHECK(node); + DCHECK(node->GetDelegate()); + + // Create a degenerate range positioned at the node's start. + AXNodePosition::AXPositionInstance start, end; + start = node->GetDelegate()->CreateTextPositionAt(0)->AsLeafTextPosition(); + end = start->Clone(); + return AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider( + node, std::move(start), std::move(end)); +} + ui::AXPlatformNodeWin* AXPlatformNodeTextProviderWin::owner() const { return owner_.Get(); } 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 d216815bd57..74984eb2a87 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win.h @@ -13,7 +13,7 @@ namespace ui { -class __declspec(uuid("3e1c192b-4348-45ac-8eb6-4b58eeb3dcca")) +class AX_EXPORT __declspec(uuid("3e1c192b-4348-45ac-8eb6-4b58eeb3dcca")) AXPlatformNodeTextProviderWin : public CComObjectRootEx, public ITextEditProvider { @@ -63,6 +63,10 @@ class __declspec(uuid("3e1c192b-4348-45ac-8eb6-4b58eeb3dcca")) ui::AXPlatformNodeWin* ancestor, ui::AXPlatformNodeWin* descendant); + // Create a dengerate text range at the start of the specified node. + static ITextRangeProvider* CreateDegenerateRangeAtStart( + ui::AXPlatformNodeWin* node); + private: friend class AXPlatformNodeTextProviderTest; ui::AXPlatformNodeWin* owner() const; diff --git a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc index 82171aac0ee..c60ba929b5a 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc @@ -52,6 +52,105 @@ class AXPlatformNodeTextProviderTest : public AXPlatformNodeWinTest { } }; +TEST_F(AXPlatformNodeTextProviderTest, CreateDegenerateRangeFromStart) { + AXNodeData text1_data; + text1_data.id = 3; + text1_data.role = ax::mojom::Role::kStaticText; + text1_data.SetName("some text"); + + AXNodeData text2_data; + text2_data.id = 4; + text2_data.role = ax::mojom::Role::kStaticText; + text2_data.SetName("more text"); + + AXNodeData link_data; + link_data.id = 2; + link_data.role = ax::mojom::Role::kLink; + link_data.child_ids = {3, 4}; + + AXNodeData root_data; + root_data.id = 1; + root_data.role = ax::mojom::Role::kRootWebArea; + root_data.SetName("Document"); + root_data.child_ids = {2}; + + AXTreeUpdate update; + AXTreeData tree_data; + tree_data.tree_id = AXTreeID::CreateNewAXTreeID(); + update.tree_data = tree_data; + update.has_tree_data = true; + update.root_id = root_data.id; + update.nodes = {root_data, link_data, text1_data, text2_data}; + + Init(update); + AXNode* root_node = GetRootAsAXNode(); + AXNode* link_node = root_node->children()[0]; + AXNode* text2_node = link_node->children()[1]; + + ComPtr root_node_raw = + QueryInterfaceFromNode(root_node); + ComPtr link_node_raw = + QueryInterfaceFromNode(link_node); + ComPtr text2_node_raw = + QueryInterfaceFromNode(text2_node); + + ComPtr root_platform_node; + EXPECT_HRESULT_SUCCEEDED( + root_node_raw->QueryInterface(IID_PPV_ARGS(&root_platform_node))); + ComPtr link_platform_node; + EXPECT_HRESULT_SUCCEEDED( + link_node_raw->QueryInterface(IID_PPV_ARGS(&link_platform_node))); + ComPtr text2_platform_node; + EXPECT_HRESULT_SUCCEEDED( + text2_node_raw->QueryInterface(IID_PPV_ARGS(&text2_platform_node))); + + // Degenerate range created on root node should be: + // <>some textmore text + ComPtr text_range_provider = + AXPlatformNodeTextProviderWin::CreateDegenerateRangeAtStart( + root_platform_node.Get()); + base::win::ScopedBstr text_content; + EXPECT_HRESULT_SUCCEEDED( + text_range_provider->GetText(-1, text_content.Receive())); + EXPECT_EQ(0, wcscmp(text_content.Get(), L"")); + + ComPtr actual_range; + text_range_provider->QueryInterface(IID_PPV_ARGS(&actual_range)); + AXNodePosition::AXPositionInstance expected_start, expected_end; + expected_start = root_platform_node->GetDelegate()->CreateTextPositionAt(0); + expected_end = expected_start->Clone(); + EXPECT_EQ(*GetStart(actual_range.Get()), *expected_start); + EXPECT_EQ(*GetEnd(actual_range.Get()), *expected_end); + text_content.Release(); + + // Degenerate range created on link node should be: + // <>some textmore text + text_range_provider = + AXPlatformNodeTextProviderWin::CreateDegenerateRangeAtStart( + link_platform_node.Get()); + EXPECT_HRESULT_SUCCEEDED( + text_range_provider->GetText(-1, text_content.Receive())); + EXPECT_EQ(0, wcscmp(text_content.Get(), L"")); + text_range_provider->QueryInterface(IID_PPV_ARGS(&actual_range)); + EXPECT_EQ(*GetStart(actual_range.Get()), *expected_start); + EXPECT_EQ(*GetEnd(actual_range.Get()), *expected_end); + text_content.Release(); + + // Degenerate range created on more text node should be: + // some text<>more text + text_range_provider = + AXPlatformNodeTextProviderWin::CreateDegenerateRangeAtStart( + text2_platform_node.Get()); + EXPECT_HRESULT_SUCCEEDED( + text_range_provider->GetText(-1, text_content.Receive())); + EXPECT_EQ(0, wcscmp(text_content.Get(), L"")); + text_range_provider->QueryInterface(IID_PPV_ARGS(&actual_range)); + expected_start = text2_platform_node->GetDelegate()->CreateTextPositionAt(0); + expected_end = expected_start->Clone(); + EXPECT_EQ(*GetStart(actual_range.Get()), *expected_start); + EXPECT_EQ(*GetEnd(actual_range.Get()), *expected_end); + text_content.Release(); +} TEST_F(AXPlatformNodeTextProviderTest, ITextProviderRangeFromChild) { AXNodeData text_data; @@ -225,10 +324,8 @@ TEST_F(AXPlatformNodeTextProviderTest, EXPECT_HRESULT_SUCCEEDED( text_range_provider->GetText(-1, text_content.Receive())); EXPECT_EQ(base::WideToUTF16(text_content.Get()), - STRING16_LITERAL("Dialog label.Dialog description.") + - kEmbeddedCharacterAsString + - STRING16_LITERAL("ok.Some more detail ") + - STRING16_LITERAL("about dialog.")); + u"Dialog label.Dialog description." + kEmbeddedCharacterAsString + + u"ok.Some more detail " + u"about dialog."); // Check the reverse relationship that GetEnclosingElement on the text range // gives back the dialog. @@ -617,7 +714,7 @@ TEST_F(AXPlatformNodeTextProviderTest, ITextProviderGetActiveComposition) { action_data.target_node_id = 1; AXPlatformNodeWin* owner = GetOwner(root_platform_node.Get()); owner->GetDelegate()->AccessibilityPerformAction(action_data); - const base::string16 active_composition_text = STRING16_LITERAL("a"); + const std::u16string active_composition_text = u"a"; owner->OnActiveComposition(gfx::Range(0, 1), active_composition_text, false); root_text_edit_provider->GetActiveComposition(&text_range_provider); @@ -677,7 +774,7 @@ TEST_F(AXPlatformNodeTextProviderTest, ITextProviderGetConversionTarget) { action_data.target_node_id = 1; AXPlatformNodeWin* owner = GetOwner(root_platform_node.Get()); owner->GetDelegate()->AccessibilityPerformAction(action_data); - const base::string16 active_composition_text = STRING16_LITERAL("a"); + const std::u16string active_composition_text = u"a"; owner->OnActiveComposition(gfx::Range(0, 1), active_composition_text, false); root_text_edit_provider->GetConversionTarget(&text_range_provider); 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 b5d734ed27a..ebe60bd8008 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc @@ -65,12 +65,13 @@ class AXRangePhysicalPixelRectDelegate : public AXRangeRectDelegate { AXNodeID node_id, int start_offset, int end_offset, + ui::AXClippingBehavior clipping_behavior, AXOffscreenResult* offscreen_result) override { AXPlatformNodeDelegate* delegate = host_->GetDelegate(tree_id, node_id); DCHECK(delegate); return delegate->GetInnerTextRangeBoundsRect( start_offset, end_offset, ui::AXCoordinateSystem::kScreenPhysicalPixels, - ui::AXClippingBehavior::kClipped, offscreen_result); + clipping_behavior, offscreen_result); } gfx::Rect GetBoundsRect(AXTreeID tree_id, @@ -436,12 +437,12 @@ HRESULT AXPlatformNodeTextRangeProviderWin::FindText( WIN_ACCESSIBILITY_API_PERF_HISTOGRAM(UMA_API_TEXTRANGE_FINDTEXT); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL_1_IN_1_OUT(string, result); - base::string16 search_string = base::WideToUTF16(string); + std::u16string search_string = base::WideToUTF16(string); if (search_string.length() <= 0) return E_INVALIDARG; size_t appended_newlines_count = 0; - base::string16 text_range = GetString(-1, &appended_newlines_count); + std::u16string text_range = GetString(-1, &appended_newlines_count); size_t find_start; size_t find_length; if (base::i18n::StringSearch(search_string, text_range, &find_start, @@ -1057,7 +1058,7 @@ AXPlatformNodeTextRangeProviderWin::GetNextTextBoundaryPosition( } } -base::string16 AXPlatformNodeTextRangeProviderWin::GetString( +std::u16string AXPlatformNodeTextRangeProviderWin::GetString( int max_count, size_t* appended_newlines_count) { AXNodeRange range(start()->Clone(), end()->Clone()); 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 e7f3f15419a..35e1096afaf 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h @@ -109,7 +109,7 @@ class AX_EXPORT __declspec(uuid("3071e40d-a10d-45ff-a59f-6e8e1138e2c1")) IFACEMETHODIMP ExpandToEnclosingUnitImpl(TextUnit unit); - base::string16 GetString(int max_count, + std::u16string GetString(int max_count, size_t* appended_newlines_count = nullptr); AXPlatformNodeWin* owner() const; const AXPositionInstance& start() const { return endpoints_.GetStart(); } 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 6c04f783f68..4224b793ead 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 @@ -327,6 +327,7 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest { ui::AXNodeData static_text2; ui::AXNodeData inline_box1; ui::AXNodeData inline_box2; + ui::AXNodeData inline_box_line_break; const int ROOT_ID = 1; const int BUTTON_ID = 2; @@ -335,8 +336,9 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest { const int STATIC_TEXT1_ID = 5; const int INLINE_BOX1_ID = 6; const int LINE_BREAK_ID = 7; - const int STATIC_TEXT2_ID = 8; - const int INLINE_BOX2_ID = 9; + const int INLINE_BOX_LINE_BREAK_ID = 8; + const int STATIC_TEXT2_ID = 9; + const int INLINE_BOX2_ID = 10; root.id = ROOT_ID; button.id = BUTTON_ID; @@ -345,6 +347,7 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest { static_text1.id = STATIC_TEXT1_ID; inline_box1.id = INLINE_BOX1_ID; line_break.id = LINE_BREAK_ID; + inline_box_line_break.id = INLINE_BOX_LINE_BREAK_ID; static_text2.id = STATIC_TEXT2_ID; inline_box2.id = INLINE_BOX2_ID; @@ -415,8 +418,22 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest { line_break.role = ax::mojom::Role::kLineBreak; line_break.AddState(ax::mojom::State::kEditable); line_break.SetName(LINE_BREAK_TEXT); + line_break.relative_bounds.bounds = gfx::RectF(250, 20, 0, 30); line_break.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId, inline_box1.id); + line_break.child_ids.push_back(inline_box_line_break.id); + + inline_box_line_break.role = ax::mojom::Role::kInlineTextBox; + inline_box_line_break.AddBoolAttribute( + ax::mojom::BoolAttribute::kIsLineBreakingObject, true); + inline_box_line_break.SetName(LINE_BREAK_TEXT); + inline_box_line_break.relative_bounds.bounds = gfx::RectF(250, 20, 0, 30); + inline_box_line_break.AddIntListAttribute( + ax::mojom::IntListAttribute::kCharacterOffsets, {0}); + inline_box_line_break.AddIntListAttribute( + ax::mojom::IntListAttribute::kWordStarts, std::vector{0}); + inline_box_line_break.AddIntListAttribute( + ax::mojom::IntListAttribute::kWordEnds, std::vector{0}); static_text2.role = ax::mojom::Role::kStaticText; static_text2.AddState(ax::mojom::State::kEditable); @@ -445,9 +462,10 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest { AXTreeUpdate update; update.has_tree_data = true; update.root_id = ROOT_ID; - update.nodes = {root, button, check_box, - text_field, static_text1, inline_box1, - line_break, static_text2, inline_box2}; + update.nodes = { + root, button, check_box, text_field, + static_text1, inline_box1, line_break, inline_box_line_break, + static_text2, inline_box2}; update.tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); return update; } @@ -2532,13 +2550,13 @@ TEST_F(AXPlatformNodeTextRangeProviderTest, // The Hindi string has two characters, the first one 32 bits and the second // 64 bits in length. It is formatted in UTF16. - const std::string hindi = base::UTF16ToUTF8( - STRING16_LITERAL("\x0939\x093F\x0928\x094D\x0926\x0940")); + const std::string hindi = + base::UTF16ToUTF8(u"\x0939\x093F\x0928\x094D\x0926\x0940"); // The Thai string has three characters, the first one 48, the second 32 and // the last one 16 bits in length. It is formatted in UTF16. - const std::string thai = base::UTF16ToUTF8( - STRING16_LITERAL("\x0E23\x0E39\x0E49\x0E2A\x0E36\x0E01")); + const std::string thai = + base::UTF16ToUTF8(u"\x0E23\x0E39\x0E49\x0E2A\x0E36\x0E01"); Init(BuildTextDocument({english, hindi, thai})); @@ -3116,7 +3134,7 @@ TEST_F(AXPlatformNodeTextRangeProviderTest, // Move the text range end back by one line. // Expected bounding rects: // Line 1
Line 2 - // |---------------------||---------------------||-----| + // |---------------------||---------------------||--------| ASSERT_HRESULT_SUCCEEDED(text_range_provider->MoveEndpointByUnit( TextPatternRangeEndpoint_End, TextUnit_Line, /*count*/ -1, &count)); ASSERT_EQ(-1, count); @@ -3133,8 +3151,8 @@ TEST_F(AXPlatformNodeTextRangeProviderTest, // Line 1
Line 2 // |---------------------||---------------------| ASSERT_HRESULT_SUCCEEDED(text_range_provider->MoveEndpointByUnit( - TextPatternRangeEndpoint_End, TextUnit_Word, /*count*/ -2, &count)); - ASSERT_EQ(-2, count); + TextPatternRangeEndpoint_End, TextUnit_Word, /*count*/ -3, &count)); + ASSERT_EQ(-3, count); EXPECT_HRESULT_SUCCEEDED( text_range_provider->GetBoundingRectangles(rectangles.Receive())); expected_values = {20, 20, 200, 30, /* button */ diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_win.cc index 44d49b91ad9..62680090cd7 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_win.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_win.cc @@ -36,6 +36,7 @@ #include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/accessibility_switches.h" #include "ui/accessibility/ax_action_data.h" +#include "ui/accessibility/ax_action_handler_registry.h" #include "ui/accessibility/ax_active_popup.h" #include "ui/accessibility/ax_constants.mojom.h" #include "ui/accessibility/ax_enum_util.h" @@ -44,7 +45,6 @@ #include "ui/accessibility/ax_node_position.h" #include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/ax_tree_data.h" -#include "ui/accessibility/ax_tree_id_registry.h" #include "ui/accessibility/platform/ax_fragment_root_win.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" #include "ui/accessibility/platform/ax_platform_node_delegate_utils_win.h" @@ -403,7 +403,7 @@ void AXPlatformNodeWin::HtmlAttributeToUIAAriaProperty( std::vector& properties, const char* html_attribute_name, const char* uia_aria_property) { - base::string16 html_attribute_value; + std::u16string html_attribute_value; if (GetData().GetHtmlAttribute(html_attribute_name, &html_attribute_value)) { std::wstring wide_value = base::UTF16ToWide(html_attribute_value); SanitizeStringAttributeForUIAAriaProperty(wide_value, &wide_value); @@ -682,7 +682,7 @@ gfx::Range AXPlatformNodeWin::GetActiveCompositionOffsets() const { void AXPlatformNodeWin::OnActiveComposition( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed) { // Cache the composition range that will be used when // GetActiveComposition and GetConversionTarget is called in @@ -1491,7 +1491,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_localizedExtendedRole( COM_OBJECT_VALIDATE_1_ARG(localized_extended_role); AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes); - base::string16 role_description = + std::u16string role_description = GetRoleDescriptionFromImageAnnotationStatusOrFromAttribute(); if (base::ContainsOnlyChars(role_description, base::kWhitespaceUTF16)) return S_FALSE; @@ -1798,20 +1798,20 @@ IFACEMETHODIMP AXPlatformNodeWin::Expand() { ExpandCollapseState AXPlatformNodeWin::ComputeExpandCollapseState() const { const AXNodeData& data = GetData(); - // Since a menu button implies there is a popup and it is either expanded or - // collapsed, and it should not support ExpandCollapseState_LeafNode. - // According to the UIA spec, ExpandCollapseState_LeafNode indicates that the - // element neither expands nor collapses. - if (data.IsMenuButton()) { - if (data.IsButtonPressed()) - return ExpandCollapseState_Expanded; - return ExpandCollapseState_Collapsed; - } - if (data.HasState(ax::mojom::State::kExpanded)) { return ExpandCollapseState_Expanded; } else if (data.HasState(ax::mojom::State::kCollapsed)) { return ExpandCollapseState_Collapsed; + } else if (data.IsMenuButton()) { + // Since a menu button implies there is a popup and it is either expanded or + // collapsed, it should not support ExpandCollapseState_LeafNode. + // According to the UIA spec, ExpandCollapseState_LeafNode indicates that + // the element neither expands nor collapses. + if (data.IsButtonPressed()) { + return ExpandCollapseState_Expanded; + } else { + return ExpandCollapseState_Collapsed; + } } else { return ExpandCollapseState_LeafNode; } @@ -3369,7 +3369,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_nCharacters(LONG* n_characters) { AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes | AXMode::kInlineTextBoxes); - base::string16 text = GetHypertext(); + std::u16string text = GetHypertext(); *n_characters = static_cast(text.size()); return S_OK; @@ -3453,14 +3453,14 @@ IFACEMETHODIMP AXPlatformNodeWin::get_text(LONG start_offset, if (start_offset > end_offset) std::swap(start_offset, end_offset); - const base::string16 str = GetHypertext(); + const std::u16string str = GetHypertext(); LONG str_len = static_cast(str.length()); if (start_offset < 0 || start_offset > str_len) return E_INVALIDARG; if (end_offset < 0 || end_offset > str_len) return E_INVALIDARG; - base::string16 substr = str.substr(start_offset, end_offset - start_offset); + std::u16string substr = str.substr(start_offset, end_offset - start_offset); if (substr.empty()) return S_FALSE; @@ -3490,7 +3490,7 @@ HRESULT AXPlatformNodeWin::IAccessibleTextGetTextForOffsetType( if (offset < 0) return E_INVALIDARG; - const base::string16& text_str = GetHypertext(); + const std::u16string& text_str = GetHypertext(); LONG text_len = text_str.length(); // https://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/interface_i_accessible_text.html @@ -3960,8 +3960,8 @@ void AXPlatformNodeWin::GetRuntimeIdArray( AXTreeID tree_id = GetDelegate()->GetTreeData().tree_id; if (data.GetIntAttribute(ax::mojom::IntAttribute::kDOMNodeId, &dom_id) && tree_id != AXTreeIDUnknown()) { - AXTreeIDRegistry::FrameID frame_id = - AXTreeIDRegistry::GetInstance()->GetFrameID(tree_id); + AXActionHandlerRegistry::FrameID frame_id = + AXActionHandlerRegistry::GetInstance()->GetFrameID(tree_id); runtime_id[1] = frame_id.first; runtime_id[2] = frame_id.second; runtime_id[3] = dom_id; @@ -4283,7 +4283,7 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id, break; case UIA_LocalizedControlTypePropertyId: { - base::string16 localized_control_type = GetRoleDescription(); + std::u16string localized_control_type = GetRoleDescription(); if (!localized_control_type.empty()) { result->vt = VT_BSTR; result->bstrVal = @@ -4440,7 +4440,7 @@ HRESULT AXPlatformNodeWin::GetPropertyValueImpl(PROPERTYID property_id, } case UIA_LocalizedLandmarkTypePropertyId: { - base::string16 localized_landmark_type = + std::u16string localized_landmark_type = GetDelegate()->GetLocalizedStringForLandmarkType(); if (!localized_landmark_type.empty()) { result->vt = VT_BSTR; @@ -4832,7 +4832,7 @@ HRESULT AXPlatformNodeWin::GetAnnotationTypesAttribute( } base::Optional AXPlatformNodeWin::GetCultureAttributeAsLCID() const { - const base::string16 language = + const std::u16string language = GetInheritedString16Attribute(ax::mojom::StringAttribute::kLanguage); const LCID lcid = LocaleNameToLCID(base::as_wcstr(language), LOCALE_ALLOW_NEUTRAL_NAMES); @@ -5334,7 +5334,6 @@ int AXPlatformNodeWin::MSAARole() { return ROLE_SYSTEM_GROUPING; case ax::mojom::Role::kImage: - case ax::mojom::Role::kImageMap: return ROLE_SYSTEM_GRAPHIC; case ax::mojom::Role::kInputTime: @@ -5835,8 +5834,9 @@ int32_t AXPlatformNodeWin::ComputeIA2Role() { case ax::mojom::Role::kIframe: ia2_role = IA2_ROLE_INTERNAL_FRAME; break; - case ax::mojom::Role::kImageMap: - ia2_role = IA2_ROLE_IMAGE_MAP; + case ax::mojom::Role::kImage: + if (IsImageWithMap()) + ia2_role = IA2_ROLE_IMAGE_MAP; break; case ax::mojom::Role::kLabelText: case ax::mojom::Role::kLegend: @@ -6166,9 +6166,6 @@ std::wstring AXPlatformNodeWin::UIAAriaRole() { case ax::mojom::Role::kImage: return L"img"; - case ax::mojom::Role::kImageMap: - return L"document"; - case ax::mojom::Role::kImeCandidate: // Internal role, not used on Windows. return L"group"; @@ -6393,7 +6390,7 @@ std::wstring AXPlatformNodeWin::UIAAriaRole() { return L"listitem"; case ax::mojom::Role::kTitleBar: - return L"document"; + return L"group"; case ax::mojom::Role::kToggleButton: return L"button"; @@ -6841,10 +6838,8 @@ LONG AXPlatformNodeWin::ComputeUIAControlType() { // NOLINT(runtime/int) return UIA_GroupControlTypeId; case ax::mojom::Role::kImage: - return UIA_ImageControlTypeId; - - case ax::mojom::Role::kImageMap: - return UIA_DocumentControlTypeId; + return IsImageWithMap() ? UIA_DocumentControlTypeId + : UIA_ImageControlTypeId; case ax::mojom::Role::kInputTime: return UIA_GroupControlTypeId; @@ -7058,7 +7053,7 @@ LONG AXPlatformNodeWin::ComputeUIAControlType() { // NOLINT(runtime/int) return UIA_ListItemControlTypeId; case ax::mojom::Role::kTitleBar: - return UIA_DocumentControlTypeId; + return UIA_TitleBarControlTypeId; case ax::mojom::Role::kToggleButton: return UIA_ButtonControlTypeId; @@ -7709,7 +7704,7 @@ BSTR AXPlatformNodeWin::GetValueAttributeAsBstr(AXPlatformNodeWin* target) { HRESULT AXPlatformNodeWin::GetStringAttributeAsBstr( ax::mojom::StringAttribute attribute, BSTR* value_bstr) const { - base::string16 str; + std::u16string str; if (!GetString16Attribute(attribute, &str)) return S_FALSE; @@ -7909,7 +7904,7 @@ BSTR AXPlatformNodeWin::GetFontNameAttributeAsBSTR() const { } BSTR AXPlatformNodeWin::GetStyleNameAttributeAsBSTR() const { - base::string16 style_name = + std::u16string style_name = GetDelegate()->GetStyleNameAttributeAsLocalizedString(); return SysAllocString(base::as_wcstr(style_name)); diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.h b/chromium/ui/accessibility/platform/ax_platform_node_win.h index 852ecc6954e..3d0cd23e480 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_win.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_win.h @@ -1097,7 +1097,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2")) // Updates the active composition range and fires UIA text edit event about // composition (active or committed) void OnActiveComposition(const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed); // Returns true if there is an active composition bool HasActiveComposition() const; 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 d309f18e006..41fe2fdf6a9 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc @@ -37,7 +37,7 @@ using base::win::ScopedVariant; namespace ui { -const base::string16 AXPlatformNodeWinTest::kEmbeddedCharacterAsString = { +const std::u16string AXPlatformNodeWinTest::kEmbeddedCharacterAsString = { ui::AXPlatformNodeBase::kEmbeddedCharacter}; namespace { @@ -3564,13 +3564,13 @@ TEST_F(AXPlatformNodeWinTest, ITableProviderGetColumnHeaders) { AXNodeData column_header; column_header.id = 3; column_header.role = ax::mojom::Role::kColumnHeader; - column_header.SetName(STRING16_LITERAL("column_header")); + column_header.SetName(u"column_header"); row1.child_ids.push_back(column_header.id); AXNodeData row_header; row_header.id = 4; row_header.role = ax::mojom::Role::kRowHeader; - row_header.SetName(STRING16_LITERAL("row_header")); + row_header.SetName(u"row_header"); row1.child_ids.push_back(row_header.id); Init(root, row1, column_header, row_header); @@ -3647,19 +3647,19 @@ TEST_F(AXPlatformNodeWinTest, ITableProviderGetColumnHeadersMultipleHeaders) { AXNodeData header_r1c1; header_r1c1.id = 5; header_r1c1.role = ax::mojom::Role::kColumnHeader; - header_r1c1.SetName(STRING16_LITERAL("header_r1c1")); + header_r1c1.SetName(u"header_r1c1"); row1.child_ids.push_back(header_r1c1.id); AXNodeData header_r1c2; header_r1c2.id = 6; header_r1c2.role = ax::mojom::Role::kColumnHeader; - header_r1c2.SetName(STRING16_LITERAL("header_r1c2")); + header_r1c2.SetName(u"header_r1c2"); row1.child_ids.push_back(header_r1c2.id); AXNodeData header_r1c3; header_r1c3.id = 7; header_r1c3.role = ax::mojom::Role::kColumnHeader; - header_r1c3.SetName(STRING16_LITERAL("header_r1c3")); + header_r1c3.SetName(u"header_r1c3"); row1.child_ids.push_back(header_r1c3.id); // @@ -3668,19 +3668,19 @@ TEST_F(AXPlatformNodeWinTest, ITableProviderGetColumnHeadersMultipleHeaders) { AXNodeData cell_r2c1; cell_r2c1.id = 8; cell_r2c1.role = ax::mojom::Role::kCell; - cell_r2c1.SetName(STRING16_LITERAL("cell_r2c1")); + cell_r2c1.SetName(u"cell_r2c1"); row2.child_ids.push_back(cell_r2c1.id); AXNodeData cell_r2c2; cell_r2c2.id = 9; cell_r2c2.role = ax::mojom::Role::kCell; - cell_r2c2.SetName(STRING16_LITERAL("cell_r2c2")); + cell_r2c2.SetName(u"cell_r2c2"); row2.child_ids.push_back(cell_r2c2.id); AXNodeData cell_r2c3; cell_r2c3.id = 10; cell_r2c3.role = ax::mojom::Role::kCell; - cell_r2c3.SetName(STRING16_LITERAL("cell_r2c3")); + cell_r2c3.SetName(u"cell_r2c3"); row2.child_ids.push_back(cell_r2c3.id); // @@ -3689,13 +3689,13 @@ TEST_F(AXPlatformNodeWinTest, ITableProviderGetColumnHeadersMultipleHeaders) { AXNodeData cell_r3c1; cell_r3c1.id = 11; cell_r3c1.role = ax::mojom::Role::kCell; - cell_r3c1.SetName(STRING16_LITERAL("cell_r3c1")); + cell_r3c1.SetName(u"cell_r3c1"); row3.child_ids.push_back(cell_r3c1.id); AXNodeData header_r3c2; header_r3c2.id = 12; header_r3c2.role = ax::mojom::Role::kColumnHeader; - header_r3c2.SetName(STRING16_LITERAL("header_r3c2")); + header_r3c2.SetName(u"header_r3c2"); row3.child_ids.push_back(header_r3c2.id); Init(root, row1, row2, row3, header_r1c1, header_r1c2, header_r1c3, cell_r2c1, @@ -3730,13 +3730,13 @@ TEST_F(AXPlatformNodeWinTest, ITableProviderGetRowHeaders) { AXNodeData column_header; column_header.id = 3; column_header.role = ax::mojom::Role::kColumnHeader; - column_header.SetName(STRING16_LITERAL("column_header")); + column_header.SetName(u"column_header"); row1.child_ids.push_back(column_header.id); AXNodeData row_header; row_header.id = 4; row_header.role = ax::mojom::Role::kRowHeader; - row_header.SetName(STRING16_LITERAL("row_header")); + row_header.SetName(u"row_header"); row1.child_ids.push_back(row_header.id); Init(root, row1, column_header, row_header); @@ -3792,13 +3792,13 @@ TEST_F(AXPlatformNodeWinTest, ITableItemProviderGetColumnHeaderItems) { AXNodeData column_header_1; column_header_1.id = 3; column_header_1.role = ax::mojom::Role::kColumnHeader; - column_header_1.SetName(STRING16_LITERAL("column_header_1")); + column_header_1.SetName(u"column_header_1"); row1.child_ids.push_back(column_header_1.id); AXNodeData column_header_2; column_header_2.id = 4; column_header_2.role = ax::mojom::Role::kColumnHeader; - column_header_2.SetName(STRING16_LITERAL("column_header_2")); + column_header_2.SetName(u"column_header_2"); row1.child_ids.push_back(column_header_2.id); AXNodeData row2; @@ -3855,7 +3855,7 @@ TEST_F(AXPlatformNodeWinTest, ITableItemProviderGetRowHeaderItems) { AXNodeData row_header_1; row_header_1.id = 3; row_header_1.role = ax::mojom::Role::kRowHeader; - row_header_1.SetName(STRING16_LITERAL("row_header_1")); + row_header_1.SetName(u"row_header_1"); row1.child_ids.push_back(row_header_1.id); AXNodeData cell; @@ -3871,7 +3871,7 @@ TEST_F(AXPlatformNodeWinTest, ITableItemProviderGetRowHeaderItems) { AXNodeData row_header_2; row_header_2.id = 6; row_header_2.role = ax::mojom::Role::kRowHeader; - row_header_2.SetName(STRING16_LITERAL("row_header_2")); + row_header_2.SetName(u"row_header_2"); row2.child_ids.push_back(row_header_2.id); Init(root, row1, row_header_1, cell, row2, row_header_2); @@ -5270,7 +5270,13 @@ TEST_F(AXPlatformNodeWinTest, ComputeUIAControlType) { child4.role = ax::mojom::Role::kSearchBox; root.child_ids.push_back(child4_id); - Init(root, child1, child2, child3, child4); + AXNodeData child5; + AXNodeID child5_id = 6; + child5.id = child5_id; + child5.role = ax::mojom::Role::kTitleBar; + root.child_ids.push_back(child5_id); + + Init(root, child1, child2, child3, child4, child5); EXPECT_UIA_INT_EQ( QueryInterfaceFromNodeId(child1_id), @@ -5284,6 +5290,9 @@ TEST_F(AXPlatformNodeWinTest, ComputeUIAControlType) { EXPECT_UIA_INT_EQ( QueryInterfaceFromNodeId(child4_id), UIA_ControlTypePropertyId, int{UIA_EditControlTypeId}); + EXPECT_UIA_INT_EQ( + QueryInterfaceFromNodeId(child5_id), + UIA_ControlTypePropertyId, int{UIA_TitleBarControlTypeId}); } TEST_F(AXPlatformNodeWinTest, UIALandmarkType) { @@ -6151,6 +6160,109 @@ TEST_F(AXPlatformNodeWinTest, IExpandCollapsePatternProviderAction) { EXPECT_EQ(ExpandCollapseState_LeafNode, state); } +// If a menu button has an expanded or collapsed state, we want to make sure we +// let that be the deciding factor for `get_ExpandCollapseState()`. Otherwise, +// check if the button is pressed. +TEST_F(AXPlatformNodeWinTest, + IExpandCollapseProviderExpandedCollapsedStateMenuButton) { + // Declare a vector that will hold our expected Expanded/Collapsed state for + // each menu button we'll declare below. + std::vector node_expected_state; + + // Our root. Will host all menu buttons below. + AXNodeData root; + root.id = 1; + root.role = ax::mojom::Role::kRootWebArea; + root.child_ids = {2, 3, 4, 5, 6, 7}; + + // If a pressed menu button is explicitly marked as `kExpanded`, its + // Expanded/Collapsed state should be expanded. + AXNodeData expanded_pressed_button; + expanded_pressed_button.id = 2; + expanded_pressed_button.role = ax::mojom::Role::kButton; + expanded_pressed_button.SetHasPopup(ax::mojom::HasPopup::kMenu); + expanded_pressed_button.SetCheckedState(ax::mojom::CheckedState::kTrue); + expanded_pressed_button.AddState(ax::mojom::State::kExpanded); + node_expected_state.push_back(ExpandCollapseState_Expanded); + + // If an unpressed menu button is explicitly marked as `kExpanded`, its + // Expanded/Collapsed state should be expanded, because this value takes + // precedence over the fact that the button isn't pressed. + AXNodeData expanded_unpressed_button; + expanded_unpressed_button.id = 3; + expanded_unpressed_button.role = ax::mojom::Role::kButton; + expanded_unpressed_button.SetHasPopup(ax::mojom::HasPopup::kMenu); + expanded_unpressed_button.SetCheckedState(ax::mojom::CheckedState::kFalse); + expanded_unpressed_button.AddState(ax::mojom::State::kExpanded); + node_expected_state.push_back(ExpandCollapseState_Expanded); + + // If a pressed menu button is explicitly marked as `kCollapsed`, its + // Expanded/Collapsed state should be collapsed, because this value takes + // precedence over the fact that the button is pressed. + AXNodeData collapsed_pressed_button; + collapsed_pressed_button.id = 4; + collapsed_pressed_button.role = ax::mojom::Role::kButton; + collapsed_pressed_button.SetHasPopup(ax::mojom::HasPopup::kMenu); + collapsed_pressed_button.SetCheckedState(ax::mojom::CheckedState::kTrue); + collapsed_pressed_button.AddState(ax::mojom::State::kCollapsed); + node_expected_state.push_back(ExpandCollapseState_Collapsed); + + // If an unpressed menu button is explicitly marked as `kCollapsed`, its + // Expanded/Collapsed state should be collapsed. + AXNodeData collapsed_unpressed_button; + collapsed_unpressed_button.id = 5; + collapsed_unpressed_button.role = ax::mojom::Role::kButton; + collapsed_unpressed_button.SetHasPopup(ax::mojom::HasPopup::kMenu); + collapsed_unpressed_button.SetCheckedState(ax::mojom::CheckedState::kFalse); + collapsed_unpressed_button.AddState(ax::mojom::State::kCollapsed); + node_expected_state.push_back(ExpandCollapseState_Collapsed); + + // If a pressed menu button has no explicit Expanded/Collapsed state, its + // Expanded/Collapsed state should be expanded (since it's pressed). + AXNodeData pressed_button; + pressed_button.id = 6; + pressed_button.role = ax::mojom::Role::kButton; + pressed_button.SetHasPopup(ax::mojom::HasPopup::kMenu); + pressed_button.SetCheckedState(ax::mojom::CheckedState::kTrue); + node_expected_state.push_back(ExpandCollapseState_Expanded); + + // If an unpressed button has no explicit Expanded/Collapsed state, its + // Expanded/Collapsed state should be collapsed (since it's unpressed). + AXNodeData unpressed_button; + unpressed_button.id = 7; + unpressed_button.role = ax::mojom::Role::kButton; + unpressed_button.SetHasPopup(ax::mojom::HasPopup::kMenu); + unpressed_button.SetCheckedState(ax::mojom::CheckedState::kFalse); + node_expected_state.push_back(ExpandCollapseState_Collapsed); + + // Initialize all our buttons as children of our root. + Init(root, expanded_pressed_button, expanded_unpressed_button, + collapsed_pressed_button, collapsed_unpressed_button, pressed_button, + unpressed_button); + + // Declare all variables we'll use in the below loop. + ComPtr raw_element_provider; + ComPtr expandcollapse_provider; + ExpandCollapseState state; + + // Loop through all child buttons and verify that we get the expected + // Expanded/Collapsed state. + CHECK_EQ(node_expected_state.size(), root.child_ids.size()); + for (size_t i = 0; i < root.child_ids.size(); ++i) { + raw_element_provider = GetIRawElementProviderSimpleFromChildIndex(i); + EXPECT_HRESULT_SUCCEEDED(raw_element_provider->GetPatternProvider( + UIA_ExpandCollapsePatternId, &expandcollapse_provider)); + 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]); + EXPECT_EQ(node_expected_state[i], state); + } +} + TEST_F(AXPlatformNodeWinTest, IInvokeProviderInvoke) { ui::AXNodeData root; root.id = 1; 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 85a66de654b..f1a31e5fe3c 100644 --- a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h +++ b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.h @@ -86,7 +86,7 @@ class AXPlatformNodeWinTest : public AXPlatformNodeTest { void TearDown() override; protected: - static const base::string16 kEmbeddedCharacterAsString; + static const std::u16string kEmbeddedCharacterAsString; AXPlatformNode* AXPlatformNodeFromNode(AXNode* node); template diff --git a/chromium/ui/accessibility/platform/ax_system_caret_win.cc b/chromium/ui/accessibility/platform/ax_system_caret_win.cc index 39c8fa17ba6..47f3ea984fc 100644 --- a/chromium/ui/accessibility/platform/ax_system_caret_win.cc +++ b/chromium/ui/accessibility/platform/ax_system_caret_win.cc @@ -28,7 +28,7 @@ AXSystemCaretWin::AXSystemCaretWin(gfx::AcceleratedWidget event_target) data_.state = 0; data_.AddState(ax::mojom::State::kInvisible); // According to MSDN, "Edit" should be the name of the caret object. - data_.SetName(STRING16_LITERAL("Edit")); + data_.SetName(u"Edit"); data_.relative_bounds.offset_container_id = -1; if (event_target_) { diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc new file mode 100644 index 00000000000..6a6210e6013 --- /dev/null +++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.cc @@ -0,0 +1,123 @@ +// 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 "base/logging.h" +#include "base/notreached.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "ui/accessibility/platform/inspect/ax_inspect.h" + +namespace ui { + +AXInspectScenario::AXInspectScenario( + const std::vector& default_filters) + : property_filters(default_filters) {} +AXInspectScenario::AXInspectScenario(AXInspectScenario&&) = default; +AXInspectScenario::~AXInspectScenario() = default; +AXInspectScenario& AXInspectScenario::operator=(AXInspectScenario&&) = default; + +// static +AXInspectScenario AXInspectScenario::From( + const std::string& directive_prefix, + const std::vector& lines, + const std::vector& default_filters) { + AXInspectScenario scenario(default_filters); + for (const std::string& line : lines) { + // Directives have format of @directive:value. + if (!base::StartsWith(line, "@")) { + continue; + } + + auto directive_end_pos = line.find_first_of(':'); + if (directive_end_pos == std::string::npos) { + continue; + } + + 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); + } + return scenario; +} + +// static +AXInspectScenario::Directive AXInspectScenario::ParseDirective( + const std::string& directive_prefix, + const std::string& directive) { + if (directive == "@NO-LOAD-EXPECTED") + return kNoLoadExpected; + if (directive == "@WAIT-FOR") + return kWaitFor; + if (directive == "@EXECUTE-AND-WAIT-FOR") + return kExecuteAndWaitFor; + if (directive == directive_prefix + "-RUN-UNTIL-EVENT") + return kRunUntil; + if (directive == "@DEFAULT-ACTION-ON") + return kDefaultActionOn; + if (directive == directive_prefix + "-ALLOW") + return kPropertyFilterAllow; + if (directive == directive_prefix + "-ALLOW-EMPTY") + return kPropertyFilterAllowEmpty; + if (directive == directive_prefix + "-DENY") + return kPropertyFilterDeny; + if (directive == directive_prefix + "-SCRIPT") + return kScript; + if (directive == directive_prefix + "-DENY-NODE") + return kNodeFilter; + + return kNone; +} + +void AXInspectScenario::ProcessDirective(Directive directive, + const std::string& value) { + switch (directive) { + case kNoLoadExpected: + no_load_expected.push_back(value); + break; + case kWaitFor: + wait_for.push_back(value); + break; + case kExecuteAndWaitFor: + execute.push_back(value); + break; + case kRunUntil: + run_until.push_back(value); + break; + case kDefaultActionOn: + default_action_on.push_back(value); + break; + case kPropertyFilterAllow: + property_filters.emplace_back(value, AXPropertyFilter::ALLOW); + break; + case kPropertyFilterAllowEmpty: + property_filters.emplace_back(value, AXPropertyFilter::ALLOW_EMPTY); + break; + case kPropertyFilterDeny: + property_filters.emplace_back(value, AXPropertyFilter::DENY); + break; + case kScript: + property_filters.emplace_back(value, AXPropertyFilter::SCRIPT); + break; + case kNodeFilter: { + const auto& parts = base::SplitString(value, "=", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + if (parts.size() == 2) + node_filters.emplace_back(parts[0], parts[1]); + else + LOG(WARNING) << "Failed to parse node filter " << value; + break; + } + default: + NOTREACHED() << "Unrecognized " << directive << " directive"; + break; + } +} + +} // namespace ui diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.h b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.h new file mode 100644 index 00000000000..9c807b9a792 --- /dev/null +++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_scenario.h @@ -0,0 +1,131 @@ +// 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_SCENARIO_H_ +#define UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_INSPECT_SCENARIO_H_ + +#include +#include + +#include "ui/accessibility/ax_export.h" + +namespace ui { + +struct AXPropertyFilter; +struct AXNodeFilter; + +// Describes the test execution flow, which is parsed from a sequence +// of testing directives (instructions). The testing directives are typically +// found in a testing file in the comment section. For example, such section +// in a dump_tree HTML test file will instruct to wait for 'bananas' text in +// a document and then dump an accessible tree which includes aria-live property +// on all platforms: +// +class AX_EXPORT AXInspectScenario { + public: + explicit AXInspectScenario( + const std::vector& default_filters = {}); + AXInspectScenario(AXInspectScenario&&); + ~AXInspectScenario(); + + AXInspectScenario& operator=(AXInspectScenario&&); + + // Parses a given testing scenario. + // @directive_prefix platform dependent directive prefix, for example, + // @MAC- is used for filter directives on Mac + // @lines lines containing directives as a text + // @default_filters set of default filters, a special type of directives, + // defining which property gets (or not) into the output, + // useful to not make each test to specify common filters + // all over + static AXInspectScenario From( + const std::string& directive_prefix, + const std::vector& lines, + const std::vector& default_filters = {}); + + // A list of URLs of resources that are never expected to load. For example, + // a broken image url, which otherwise would make a test failing. + std::vector no_load_expected; + + // A list of strings must be present in the formatted tree before the test + // starts + std::vector wait_for; + + // A list of string indicating an element the default accessible action + // should be performed at before the test starts. + std::vector default_action_on; + + // A list of JavaScripts functions to be executed consequently. Function + // may return a value, which has to be present in a formatter tree before + // the next function evaluated. + std::vector execute; + + // A list of strings indicating that event recording should be terminated + // when one of them is present in a formatted tree. + std::vector run_until; + + // A list of property filters which defines generated output of a formatted + // tree. + std::vector property_filters; + + // The node filters indicating subtrees that should be not included into + // a formatted tree. + std::vector node_filters; + + private: + enum Directive { + // No directive. + kNone, + + // Instructs to not wait for document load for url defined by the + // directive. + kNoLoadExpected, + + // Delays a test unitl a string defined by the directive is present + // in the dump. + kWaitFor, + + // Delays a test until a string returned by a script defined by the + // directive is present in the dump. + kExecuteAndWaitFor, + + // Indicates event recording should continue at least until a specific + // event has been received. + kRunUntil, + + // Invokes default action on an accessible object defined by the + // directive. + kDefaultActionOn, + + // Property filter directives, see AXPropertyFilter. + kPropertyFilterAllow, + kPropertyFilterAllowEmpty, + kPropertyFilterDeny, + + // Scripting instruction. + kScript, + + // Node filter directives, see AXNodeFilter. + kNodeFilter, + }; + + // Parses directives from the given line. + static Directive ParseDirective(const std::string& directive_prefix, + const std::string& directive); + + // Adds a given directive into a scenario. + void ProcessDirective(Directive directive, const std::string& value); +}; + +} // namespace ui + +#endif // UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_INSPECT_SCENARIO_H_ 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 6d74b176c90..651f582d7ee 100644 --- a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc +++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.cc @@ -4,7 +4,6 @@ #include "ui/accessibility/platform/inspect/ax_inspect_utils_win.h" -#include #include #include @@ -12,6 +11,7 @@ #include "base/memory/singleton.h" #include "base/stl_util.h" +#include "base/strings/pattern.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "third_party/iaccessible2/ia2_api_all.h" @@ -20,10 +20,10 @@ namespace ui { namespace { -const wchar_t kChromeTitle[] = L"Google Chrome"; -const wchar_t kChromiumTitle[] = L"Chromium"; -const wchar_t kEdgeTitle[] = L"Edge"; -const wchar_t kFirefoxTitle[] = L"Firefox"; +constexpr wchar_t kChromeTitle[] = L"Google Chrome"; +constexpr wchar_t kChromiumTitle[] = L"Chromium"; +constexpr wchar_t kEdgeTitle[] = L"Edge"; +constexpr wchar_t kFirefoxTitle[] = L"Mozilla Firefox"; struct PlatformConstantToNameEntry { int32_t value; @@ -366,6 +366,7 @@ AX_EXPORT std::wstring UiaIdentifierToString(int32_t identifier) { QUOTE(UIA_CustomNavigationPatternId), QUOTE(UIA_SelectionPattern2Id), // Events + QUOTE(UIA_ActiveTextPositionChangedEventId), QUOTE(UIA_ToolTipOpenedEventId), QUOTE(UIA_ToolTipClosedEventId), QUOTE(UIA_StructureChangedEventId), @@ -700,24 +701,29 @@ AX_EXPORT HWND GetHwndForProcess(base::ProcessId pid) { struct HWNDSearchInfo { std::wstring title; - HWND hwnd; + std::wstring pattern; + HWND matched_hwnd{nullptr}; + std::vector matched_titles; }; BOOL CALLBACK MatchWindow(HWND hwnd, LPARAM lParam) { - const auto num_chars = ::GetWindowTextLength(hwnd); - if (!num_chars) { + int length = ::GetWindowTextLength(hwnd); + if (length == 0) { return TRUE; } - std::wstring title(num_chars + 1, '\0'); - if (!::GetWindowText(hwnd, &title.front(), title.size())) { - return TRUE; - } + std::wstring title(length, '\0'); + int actual_length = ::GetWindowText(hwnd, &title.front(), title.size() + 1); + if (length > actual_length) + title.erase(actual_length); auto* info = reinterpret_cast(lParam); - if (title.find(info->title) != std::wstring::npos) { - info->hwnd = hwnd; - return FALSE; + if (base::EndsWith(title, info->title) && + (info->pattern.empty() || + base::MatchPattern(base::AsStringPiece16(title), + base::AsStringPiece16(info->pattern)))) { + info->matched_titles.push_back(title); + info->matched_hwnd = hwnd; } return TRUE; } @@ -732,17 +738,87 @@ AX_EXPORT HWND GetHWNDBySelector(const AXTreeSelector& selector) { info.title = kEdgeTitle; } else if (selector.types & AXTreeSelector::Firefox) { info.title = kFirefoxTitle; - } else { + } + + if (!selector.pattern.empty()) { + info.pattern = base::UTF8ToWide(selector.pattern); + } else if (info.title.empty()) { LOG(ERROR) << selector.AppName() << " application is not supported on the system"; return NULL; } - if (::EnumWindows(MatchWindow, reinterpret_cast(&info))) { + // A match is found when the window title ends with the search title + // and matches the search pattern when provided. + // Note that both the search title and pattern are optional, but at + // least one should be provided. + DCHECK(!info.title.empty() || !info.pattern.empty()); + + ::EnumWindows(MatchWindow, reinterpret_cast(&info)); + + // Fail if multiple matches are found. + if (info.matched_titles.size() > 1) { + LOG(ERROR) << "Ambiguous name: multiple windows matched:"; + for (auto title : info.matched_titles) { + LOG(ERROR) << " " << title; + // Extra empty log to avoid jamming titles together. Apparently titles + // contain special characters that prevent from printing anything coming + // afterwards. + LOG(ERROR) << ""; + } return NULL; } - return info.hwnd; + return info.matched_hwnd; +} + +MSAAChild::MSAAChild() = default; +MSAAChild::MSAAChild(IAccessible* parent, VARIANT&& variant) : parent_(parent) { + child_variant_.Reset(variant); + + Microsoft::WRL::ComPtr dispatch; + if (child_variant_.type() == VT_DISPATCH) { + dispatch = V_DISPATCH(child_variant_.ptr()); + } else if (child_variant_.type() == VT_I4) { + if (FAILED(parent->get_accChild(child_variant_, &dispatch))) { + child_variant_.Reset(); + } + } + + if (dispatch) { + if (FAILED(dispatch.As(&child_))) { + child_ = nullptr; + } + } +} +MSAAChild::MSAAChild(MSAAChild&&) = default; +MSAAChild::~MSAAChild() = default; + +MSAAChildren::MSAAChildren(IAccessible* parent) { + if (FAILED(parent->get_accChildCount(&count_))) + return; + + std::unique_ptr children_variants(new VARIANT[count_]); + if (FAILED(AccessibleChildren(parent, 0, count_, children_variants.get(), + &count_))) { + count_ = 0; + return; + } + + children_.reserve(count_); + for (LONG i = 0; i < count_; i++) + children_.emplace_back(parent, std::move(children_variants[i])); } +MSAAChildren::MSAAChildren(const Microsoft::WRL::ComPtr& parent) + : MSAAChildren(parent.Get()) {} +MSAAChildren::~MSAAChildren() = default; + +MSAAChildren::Iterator::Iterator(MSAAChildren* children) + : children_(children) {} +MSAAChildren::Iterator::Iterator(MSAAChildren* children, LONG index) + : index_(index), children_(children) {} +MSAAChildren::Iterator::Iterator(const Iterator&) = default; +MSAAChildren::Iterator::~Iterator() = default; + } // namespace ui diff --git a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.h b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.h index 64f6f775afc..23d9b815cd8 100644 --- a/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.h +++ b/chromium/ui/accessibility/platform/inspect/ax_inspect_utils_win.h @@ -11,7 +11,11 @@ #include #include +#include +#include + #include "base/process/process_handle.h" +#include "base/win/scoped_variant.h" #include "ui/accessibility/ax_export.h" #include "ui/gfx/win/hwnd_util.h" @@ -44,6 +48,74 @@ AX_EXPORT HWND GetHwndForProcess(base::ProcessId pid); // Returns HWND of window matching a given tree selector. AX_EXPORT HWND GetHWNDBySelector(const ui::AXTreeSelector& selector); +// Represent MSAA child, either as IAccessible object or as VARIANT. +class AX_EXPORT MSAAChild final { + public: + MSAAChild(); + MSAAChild(IAccessible* parent, VARIANT&& child); + MSAAChild(MSAAChild&&); + ~MSAAChild(); + + MSAAChild& operator=(MSAAChild&& rhs) = default; + + IAccessible* AsIAccessible() const { return child_.Get(); } + const base::win::ScopedVariant& AsVariant() const { return child_variant_; } + + IAccessible* Parent() const { return parent_.Get(); } + + private: + Microsoft::WRL::ComPtr parent_; + Microsoft::WRL::ComPtr child_; + base::win::ScopedVariant child_variant_; +}; + +// Represents MSAA children of an IAccessible object. +class AX_EXPORT MSAAChildren final { + public: + MSAAChildren(IAccessible* parent); + MSAAChildren(const Microsoft::WRL::ComPtr& parent); + ~MSAAChildren(); + + const MSAAChild& ChildAt(LONG index) const { return children_[index]; } + IAccessible* Parent() const { return parent_.Get(); } + + class AX_EXPORT Iterator final + : public std::iterator { + public: + Iterator(MSAAChildren*); + Iterator(MSAAChildren*, LONG); + Iterator(const Iterator&); + ~Iterator(); + + Iterator& operator++() { + ++index_; + return *this; + } + Iterator operator++(int) { + Iterator tmp(*this); + operator++(); + return tmp; + } + bool operator==(const Iterator& rhs) const { + return children_ == rhs.children_ && index_ == rhs.index_; + } + bool operator!=(const Iterator& rhs) const { return !operator==(rhs); } + const MSAAChild& operator*() { return children_->ChildAt(index_); } + + private: + LONG index_{0}; + MSAAChildren* children_{nullptr}; + }; + + Iterator begin() { return {this}; } + Iterator end() { return {this, count_}; } + + private: + LONG count_{-1}; + Microsoft::WRL::ComPtr parent_{nullptr}; + std::vector children_; +}; + } // namespace ui #endif // UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_INSPECT_UTILS_WIN_H_ diff --git a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter.h b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter.h index f8f6dbde568..c4182cfbc30 100644 --- a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter.h +++ b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter.h @@ -50,6 +50,13 @@ class AX_EXPORT AXTreeFormatter { // |root| must be non-null and must be in web content. virtual std::string Format(AXPlatformNodeDelegate* root) const = 0; + // Formats a given web node (i.e. without children). + virtual std::string FormatNode(AXPlatformNodeDelegate* node) const = 0; + + // Similar to BuildTree, but generates a dictionary just for the current + // web node (i.e. without children). + virtual base::Value BuildNode(AXPlatformNodeDelegate* node) const = 0; + // Build an accessibility tree for any window. // // Returns a dictionary value with the accessibility tree populated. 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 f3dd6709288..6090b835340 100644 --- a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc +++ b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.cc @@ -34,6 +34,15 @@ std::string AXTreeFormatterBase::Format(AXPlatformNodeDelegate* root) const { return FormatTree(BuildTree(root)); } +std::string AXTreeFormatterBase::FormatNode( + AXPlatformNodeDelegate* node) const { + return FormatTree(BuildNode(node)); +} + +base::Value AXTreeFormatterBase::BuildNode(AXPlatformNodeDelegate* node) const { + return base::Value(base::Value::Type::DICTIONARY); +} + std::string AXTreeFormatterBase::FormatTree(const base::Value& dict) const { std::string contents; 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 e5704194822..45e80bfb231 100644 --- a/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h +++ b/chromium/ui/accessibility/platform/inspect/ax_tree_formatter_base.h @@ -26,6 +26,9 @@ class AX_EXPORT AXTreeFormatterBase : public AXTreeFormatter { // Dumps formatted the given accessibility tree into a string. std::string Format(AXPlatformNodeDelegate* root) const override; + // Dumps the given accessibility node out as a string. + std::string FormatNode(AXPlatformNodeDelegate* node) const override; + // Build an accessibility tree for the current Chrome app. virtual base::Value BuildTree(AXPlatformNodeDelegate* root) const = 0; @@ -100,6 +103,8 @@ class AX_EXPORT AXTreeFormatterBase : public AXTreeFormatter { AXPropertyFilter::Type type = AXPropertyFilter::ALLOW); bool show_ids() const { return show_ids_; } + base::Value BuildNode(ui::AXPlatformNodeDelegate* node) const override; + private: void RecursiveFormatTree(const base::Value& tree_node, std::string* contents, diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc index 00f48c746b8..14f827c5072 100644 --- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc +++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc @@ -667,29 +667,29 @@ bool TestAXNodeWrapper::AccessibilityPerformAction( } } -base::string16 TestAXNodeWrapper::GetLocalizedRoleDescriptionForUnlabeledImage() +std::u16string TestAXNodeWrapper::GetLocalizedRoleDescriptionForUnlabeledImage() const { - return base::ASCIIToUTF16("Unlabeled image"); + return u"Unlabeled image"; } -base::string16 TestAXNodeWrapper::GetLocalizedStringForLandmarkType() const { +std::u16string TestAXNodeWrapper::GetLocalizedStringForLandmarkType() const { const AXNodeData& data = GetData(); switch (data.role) { case ax::mojom::Role::kBanner: case ax::mojom::Role::kHeader: - return base::ASCIIToUTF16("banner"); + return u"banner"; case ax::mojom::Role::kComplementary: - return base::ASCIIToUTF16("complementary"); + return u"complementary"; case ax::mojom::Role::kContentInfo: case ax::mojom::Role::kFooter: - return base::ASCIIToUTF16("content information"); + return u"content information"; case ax::mojom::Role::kRegion: case ax::mojom::Role::kSection: if (data.HasStringAttribute(ax::mojom::StringAttribute::kName)) - return base::ASCIIToUTF16("region"); + return u"region"; FALLTHROUGH; default: @@ -697,138 +697,138 @@ base::string16 TestAXNodeWrapper::GetLocalizedStringForLandmarkType() const { } } -base::string16 TestAXNodeWrapper::GetLocalizedStringForRoleDescription() const { +std::u16string TestAXNodeWrapper::GetLocalizedStringForRoleDescription() const { const AXNodeData& data = GetData(); switch (data.role) { case ax::mojom::Role::kArticle: - return base::ASCIIToUTF16("article"); + return u"article"; case ax::mojom::Role::kAudio: - return base::ASCIIToUTF16("audio"); + return u"audio"; case ax::mojom::Role::kCode: - return base::ASCIIToUTF16("code"); + return u"code"; case ax::mojom::Role::kColorWell: - return base::ASCIIToUTF16("color picker"); + return u"color picker"; case ax::mojom::Role::kContentInfo: - return base::ASCIIToUTF16("content information"); + return u"content information"; case ax::mojom::Role::kDate: - return base::ASCIIToUTF16("date picker"); + return u"date picker"; case ax::mojom::Role::kDateTime: { std::string input_type; if (data.GetStringAttribute(ax::mojom::StringAttribute::kInputType, &input_type)) { if (input_type == "datetime-local") { - return base::ASCIIToUTF16("local date and time picker"); + return u"local date and time picker"; } else if (input_type == "week") { - return base::ASCIIToUTF16("week picker"); + return u"week picker"; } } return {}; } case ax::mojom::Role::kDetails: - return base::ASCIIToUTF16("details"); + return u"details"; case ax::mojom::Role::kEmphasis: - return base::ASCIIToUTF16("emphasis"); + return u"emphasis"; case ax::mojom::Role::kFigure: - return base::ASCIIToUTF16("figure"); + return u"figure"; case ax::mojom::Role::kFooter: case ax::mojom::Role::kFooterAsNonLandmark: - return base::ASCIIToUTF16("footer"); + return u"footer"; case ax::mojom::Role::kHeader: case ax::mojom::Role::kHeaderAsNonLandmark: - return base::ASCIIToUTF16("header"); + return u"header"; case ax::mojom::Role::kMark: - return base::ASCIIToUTF16("highlight"); + return u"highlight"; case ax::mojom::Role::kMeter: - return base::ASCIIToUTF16("meter"); + return u"meter"; case ax::mojom::Role::kSearchBox: - return base::ASCIIToUTF16("search box"); + return u"search box"; case ax::mojom::Role::kSection: { if (data.HasStringAttribute(ax::mojom::StringAttribute::kName)) - return base::ASCIIToUTF16("section"); + return u"section"; return {}; } case ax::mojom::Role::kStatus: - return base::ASCIIToUTF16("output"); + return u"output"; case ax::mojom::Role::kStrong: - return base::ASCIIToUTF16("strong"); + return u"strong"; case ax::mojom::Role::kTextField: { std::string input_type; if (data.GetStringAttribute(ax::mojom::StringAttribute::kInputType, &input_type)) { if (input_type == "email") { - return base::ASCIIToUTF16("email"); + return u"email"; } else if (input_type == "tel") { - return base::ASCIIToUTF16("telephone"); + return u"telephone"; } else if (input_type == "url") { - return base::ASCIIToUTF16("url"); + return u"url"; } } return {}; } case ax::mojom::Role::kTime: - return base::ASCIIToUTF16("time"); + return u"time"; default: return {}; } } -base::string16 TestAXNodeWrapper::GetLocalizedStringForImageAnnotationStatus( +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."); case ax::mojom::ImageAnnotationStatus::kAnnotationPending: - return base::ASCIIToUTF16("Getting description..."); + return u"Getting description..."; case ax::mojom::ImageAnnotationStatus::kAnnotationAdult: return base::ASCIIToUTF16( "Appears to contain adult content. No description available."); case ax::mojom::ImageAnnotationStatus::kAnnotationEmpty: case ax::mojom::ImageAnnotationStatus::kAnnotationProcessFailed: - return base::ASCIIToUTF16("No description available."); + return u"No description available."; case ax::mojom::ImageAnnotationStatus::kNone: case ax::mojom::ImageAnnotationStatus::kWillNotAnnotateDueToScheme: case ax::mojom::ImageAnnotationStatus::kIneligibleForAnnotation: case ax::mojom::ImageAnnotationStatus::kSilentlyEligibleForAnnotation: case ax::mojom::ImageAnnotationStatus::kAnnotationSucceeded: - return base::string16(); + return std::u16string(); } NOTREACHED(); - return base::string16(); + return std::u16string(); } -base::string16 TestAXNodeWrapper::GetStyleNameAttributeAsLocalizedString() +std::u16string TestAXNodeWrapper::GetStyleNameAttributeAsLocalizedString() const { AXNode* current_node = node_; while (current_node) { if (current_node->data().role == ax::mojom::Role::kMark) - return base::ASCIIToUTF16("mark"); + return u"mark"; current_node = current_node->parent(); } - return base::string16(); + return std::u16string(); } bool TestAXNodeWrapper::ShouldIgnoreHoveredStateForTesting() { @@ -994,6 +994,17 @@ gfx::RectF TestAXNodeWrapper::GetInlineTextRect(const int start_offset, return bounds; } +bool TestAXNodeWrapper::Intersects(gfx::RectF rect1, gfx::RectF rect2) const { + // The logic below is based on gfx::RectF::Intersects. + // gfx::RectF::Intersects returns false if either of the two rects is empty. + // This function is used in tests to determine offscreen status. We want to + // include empty rect in our logic since the bounding box of a degenerate text + // range is initially empty (width=0), and we do not want to mark it as + // offscreen. + return rect1.x() < rect2.right() && rect1.right() > rect2.x() && + rect1.y() < rect2.bottom() && rect1.bottom() > rect2.y(); +} + AXOffscreenResult TestAXNodeWrapper::DetermineOffscreenResult( gfx::RectF bounds) const { if (!tree_ || !tree_->root()) @@ -1008,13 +1019,14 @@ AXOffscreenResult TestAXNodeWrapper::DetermineOffscreenResult( // the bounds of the immediate parent of the node for determining offscreen // status. // We only determine offscreen result if the root web area bounds is actually - // set in the test. We default the offscreen result of every other situation - // to AXOffscreenResult::kOnscreen. - if (!root_web_area_bounds.IsEmpty()) { - bounds.Intersect(root_web_area_bounds); - if (bounds.IsEmpty()) - return AXOffscreenResult::kOffscreen; + // set in the test, and we mark a node as offscreen only when |bounds| is + // completely outside of |root_web_area_bounds|. We default the offscreen + // result of every other situation to AXOffscreenResult::kOnscreen. + if (!root_web_area_bounds.IsEmpty() && + !Intersects(root_web_area_bounds, bounds)) { + return AXOffscreenResult::kOffscreen; } + return AXOffscreenResult::kOnscreen; } diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h index 506906c0cb8..b46628b22a2 100644 --- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h +++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h @@ -127,12 +127,12 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegateBase { bool IsCellOrHeaderOfARIAGrid() const override; gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override; bool AccessibilityPerformAction(const AXActionData& data) override; - base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() const override; - base::string16 GetLocalizedStringForLandmarkType() const override; - base::string16 GetLocalizedStringForRoleDescription() const override; - base::string16 GetLocalizedStringForImageAnnotationStatus( + std::u16string GetLocalizedRoleDescriptionForUnlabeledImage() const override; + std::u16string GetLocalizedStringForLandmarkType() const override; + std::u16string GetLocalizedStringForRoleDescription() const override; + std::u16string GetLocalizedStringForImageAnnotationStatus( ax::mojom::ImageAnnotationStatus status) const override; - base::string16 GetStyleNameAttributeAsLocalizedString() const override; + std::u16string GetStyleNameAttributeAsLocalizedString() const override; bool ShouldIgnoreHoveredStateForTesting() override; const ui::AXUniqueId& GetUniqueId() const override; bool HasVisibleCaretOrSelection() const override; @@ -178,7 +178,11 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegateBase { gfx::RectF GetInlineTextRect(const int start_offset, const int end_offset) const; - // Determine the offscreen status of a particular element given its bounds.. + // Helper for determining if the two rects, including empty rects, intersect + // each other. + bool Intersects(gfx::RectF rect1, gfx::RectF rect2) const; + + // Determine the offscreen status of a particular element given its bounds. AXOffscreenResult DetermineOffscreenResult(gfx::RectF bounds) const; AXTree* tree_; diff --git a/chromium/ui/accessibility/test_ax_node_helper.cc b/chromium/ui/accessibility/test_ax_node_helper.cc index b7e85af537a..4ab41b28826 100644 --- a/chromium/ui/accessibility/test_ax_node_helper.cc +++ b/chromium/ui/accessibility/test_ax_node_helper.cc @@ -178,6 +178,17 @@ gfx::RectF TestAXNodeHelper::GetInlineTextRect(const int start_offset, return bounds; } +bool TestAXNodeHelper::Intersects(gfx::RectF rect1, gfx::RectF rect2) const { + // The logic below is based on gfx::RectF::Intersects. + // gfx::RectF::Intersects returns false if either of the two rects is empty. + // This function is used in tests to determine offscreen status. We want to + // include empty rect in our logic since the bounding box of a degenerate text + // range is initially empty (width=0), and we do not want to mark it as + // offscreen. + return rect1.x() < rect2.right() && rect1.right() > rect2.x() && + rect1.y() < rect2.bottom() && rect1.bottom() > rect2.y(); +} + AXOffscreenResult TestAXNodeHelper::DetermineOffscreenResult( gfx::RectF bounds) const { if (!tree_ || !tree_->root()) @@ -192,13 +203,15 @@ AXOffscreenResult TestAXNodeHelper::DetermineOffscreenResult( // the bounds of the immediate parent of the node for determining offscreen // status. // We only determine offscreen result if the root web area bounds is actually - // set in the test. We default the offscreen result of every other situation - // to AXOffscreenResult::kOnscreen. - if (!root_web_area_bounds.IsEmpty()) { - bounds.Intersect(root_web_area_bounds); - if (bounds.IsEmpty()) - return AXOffscreenResult::kOffscreen; + // set in the test, and we mark a node as offscreen only when |bounds| is + // completely outside of |root_web_area_bounds| (i.e. not contained by + // |root_web_area_bounds|). We default the offscreen result of every other + // situation to AXOffscreenResult::kOnscreen. + if (!root_web_area_bounds.IsEmpty() && + !Intersects(bounds, root_web_area_bounds)) { + return AXOffscreenResult::kOffscreen; } + return AXOffscreenResult::kOnscreen; } } // namespace ui diff --git a/chromium/ui/accessibility/test_ax_node_helper.h b/chromium/ui/accessibility/test_ax_node_helper.h index a303b81abf9..360e58f12fe 100644 --- a/chromium/ui/accessibility/test_ax_node_helper.h +++ b/chromium/ui/accessibility/test_ax_node_helper.h @@ -39,6 +39,11 @@ class TestAXNodeHelper { gfx::RectF GetLocation() const; gfx::RectF GetInlineTextRect(const int start_offset, const int end_offset) const; + // Helper for determining if the two rects, including empty rects, intersect + // each other. + bool Intersects(gfx::RectF rect1, gfx::RectF rect2) const; + + // Determine the offscreen status of a particular element given its bounds. AXOffscreenResult DetermineOffscreenResult(gfx::RectF bounds) const; AXTree* tree_; diff --git a/chromium/ui/android/BUILD.gn b/chromium/ui/android/BUILD.gn index ad00a4dc7e1..5358a597b15 100644 --- a/chromium/ui/android/BUILD.gn +++ b/chromium/ui/android/BUILD.gn @@ -182,6 +182,7 @@ android_resources("ui_java_resources") { "java/res/drawable-xxxhdpi/popup_bg.9.png", "java/res/drawable/custom_toast_background.xml", "java/res/drawable/drag_handlebar.xml", + "java/res/drawable/ic_apps_blue_24dp.xml", "java/res/drawable/ic_expand_more_horizontal_black_24dp.xml", "java/res/drawable/popup_bg_tinted.xml", "java/res/font/accent_font.xml", @@ -289,6 +290,7 @@ android_library("ui_no_recycler_view_java") { "java/src/org/chromium/ui/drawable/AnimationLooper.java", "java/src/org/chromium/ui/drawable/StateListDrawableBuilder.java", "java/src/org/chromium/ui/events/devices/InputDeviceObserver.java", + "java/src/org/chromium/ui/gfx/AdpfRenderingStageScheduler.java", "java/src/org/chromium/ui/gfx/Animation.java", "java/src/org/chromium/ui/gfx/BitmapHelper.java", "java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java", @@ -347,6 +349,7 @@ android_library("ui_no_recycler_view_java") { "java/src/org/chromium/ui/widget/ChromeBulletSpan.java", "java/src/org/chromium/ui/widget/ChromeImageButton.java", "java/src/org/chromium/ui/widget/ChromeImageView.java", + "java/src/org/chromium/ui/widget/LoadingView.java", "java/src/org/chromium/ui/widget/OptimizedFrameLayout.java", "java/src/org/chromium/ui/widget/RectProvider.java", "java/src/org/chromium/ui/widget/RippleBackgroundHelper.java", @@ -361,7 +364,7 @@ android_library("ui_no_recycler_view_java") { ":ui_java_resources", ":ui_utils_java", "//base:base_java", - "//base:jni_java", + "//components/url_formatter/android:url_formatter_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_appcompat_appcompat_java", "//third_party/androidx:androidx_appcompat_appcompat_resources_java", @@ -464,6 +467,7 @@ junit_binary("ui_junit_tests") { "junit/src/org/chromium/ui/text/SpanApplierTest.java", "junit/src/org/chromium/ui/util/TokenHolderTest.java", "junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java", + "junit/src/org/chromium/ui/widget/LoadingViewTest.java", "junit/src/org/chromium/ui/widget/ViewLookupCachingFrameLayoutTest.java", ] deps = [ @@ -533,7 +537,6 @@ android_library("clipboard_java_test_support") { deps = [ "//base:base_java", "//base:base_java_test_support", - "//base:jni_java", ] } @@ -548,9 +551,9 @@ android_library("ui_javatests") { ":ui_java_test_support", "//base:base_java", "//base:base_java_test_support", - "//base:jni_java", "//content/public/test/android:content_java_test_support", "//third_party/androidx:androidx_test_runner_java", + "//third_party/hamcrest:hamcrest_library_java", "//third_party/junit", ] } diff --git a/chromium/ui/android/DEPS b/chromium/ui/android/DEPS index ff9c6b8bdb2..c01147820a9 100644 --- a/chromium/ui/android/DEPS +++ b/chromium/ui/android/DEPS @@ -8,6 +8,7 @@ include_rules = [ "+cc/test/test_task_graph_runner.h", "+cc/trees/layer_tree_host.h", "+cc/trees/swap_promise.h", + "+components/url_formatter", "+components/viz/client", "+components/viz/common", "+components/viz/host", diff --git a/chromium/ui/android/delegated_frame_host_android.cc b/chromium/ui/android/delegated_frame_host_android.cc index 856c0f56933..a1ed0d9158d 100644 --- a/chromium/ui/android/delegated_frame_host_android.cc +++ b/chromium/ui/android/delegated_frame_host_android.cc @@ -123,7 +123,8 @@ void DelegatedFrameHostAndroid::CopyFromCompositingSurface( std::unique_ptr readback_ref, std::unique_ptr result) { - std::move(callback).Run(result->AsSkBitmap()); + auto scoped_bitmap = result->ScopedAccessSkBitmap(); + std::move(callback).Run(scoped_bitmap.GetOutScopedBitmap()); }, std::move(callback), std::move(readback_ref))); @@ -273,7 +274,7 @@ void DelegatedFrameHostAndroid::EmbedSurface( bool has_fallback_surface = (content_layer_->oldest_acceptable_fallback() && content_layer_->oldest_acceptable_fallback()->is_valid()); - local_surface_id_ = new_local_surface_id; + SetLocalSurfaceId(new_local_surface_id); // The embedding of a new surface completes the navigation process. pre_navigation_local_surface_id_ = viz::LocalSurfaceId(); // Navigations performed while hidden delay embedding until transitioning to @@ -352,6 +353,12 @@ viz::SurfaceId DelegatedFrameHostAndroid::SurfaceId() const { return viz::SurfaceId(frame_sink_id_, local_surface_id_); } +void DelegatedFrameHostAndroid::SetLocalSurfaceId( + const viz::LocalSurfaceId& local_surface_id) { + local_surface_id_ = local_surface_id; + client_->OnSurfaceIdChanged(); +} + bool DelegatedFrameHostAndroid::HasPrimarySurface() const { return content_layer_->surface_id().is_valid(); } @@ -393,7 +400,7 @@ void DelegatedFrameHostAndroid::OnNavigateToNewPage() { // evict it when transitioning to becoming visible. pre_navigation_local_surface_id_ = local_surface_id_; first_local_surface_id_after_navigation_ = viz::LocalSurfaceId(); - local_surface_id_ = viz::LocalSurfaceId(); + SetLocalSurfaceId(viz::LocalSurfaceId()); } void DelegatedFrameHostAndroid::SetTopControlsVisibleHeight(float height) { diff --git a/chromium/ui/android/delegated_frame_host_android.h b/chromium/ui/android/delegated_frame_host_android.h index b8ae91290ac..d2ae38cca35 100644 --- a/chromium/ui/android/delegated_frame_host_android.h +++ b/chromium/ui/android/delegated_frame_host_android.h @@ -42,6 +42,7 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid virtual void OnFrameTokenChanged(uint32_t frame_token, base::TimeTicks activation_time) = 0; virtual void WasEvicted() = 0; + virtual void OnSurfaceIdChanged() = 0; }; DelegatedFrameHostAndroid(ViewAndroid* view, @@ -147,6 +148,8 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid void ProcessCopyOutputRequest( std::unique_ptr request); + void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id); + const viz::FrameSinkId frame_sink_id_; ViewAndroid* view_; diff --git a/chromium/ui/android/event_forwarder.cc b/chromium/ui/android/event_forwarder.cc index 8eac9e2ecbf..6a9820767b6 100644 --- a/chromium/ui/android/event_forwarder.cc +++ b/chromium/ui/android/event_forwarder.cc @@ -133,7 +133,7 @@ void EventForwarder::OnDragEvent(JNIEnv* env, float dip_scale = view_->GetDipScale(); gfx::PointF location(x / dip_scale, y / dip_scale); gfx::PointF root_location(screen_x / dip_scale, screen_y / dip_scale); - std::vector mime_types; + std::vector mime_types; AppendJavaStringArrayToStringVector(env, j_mimeTypes, &mime_types); DragEventAndroid event(env, action, location, root_location, mime_types, diff --git a/chromium/ui/android/junit/src/org/chromium/ui/widget/LoadingViewTest.java b/chromium/ui/android/junit/src/org/chromium/ui/widget/LoadingViewTest.java new file mode 100644 index 00000000000..282a1c96c91 --- /dev/null +++ b/chromium/ui/android/junit/src/org/chromium/ui/widget/LoadingViewTest.java @@ -0,0 +1,133 @@ +// 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. + +package org.chromium.ui.widget; + +import android.app.Activity; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; +import org.robolectric.shadows.ShadowView; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.CallbackHelper; + +import java.util.concurrent.TimeUnit; + +/** + * Tests for {@link LoadingView}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowView.class}) +public class LoadingViewTest { + static class TestObserver implements LoadingView.Observer { + public final CallbackHelper showLoadingCallback = new CallbackHelper(); + public final CallbackHelper hideLoadingCallback = new CallbackHelper(); + + @Override + public void onShowLoadingUIComplete() { + showLoadingCallback.notifyCalled(); + } + + @Override + public void onHideLoadingUIComplete() { + hideLoadingCallback.notifyCalled(); + } + } + + private LoadingView mLoadingView; + private Activity mActivity; + private final TestObserver mTestObserver1 = new TestObserver(); + private final TestObserver mTestObserver2 = new TestObserver(); + + @Before + public void setUpTest() throws Exception { + mActivity = Robolectric.buildActivity(Activity.class).create().get(); + + FrameLayout content = new FrameLayout(mActivity); + mActivity.setContentView(content); + + mLoadingView = new LoadingView(mActivity); + mLoadingView.setDisableAnimationForTest(true); + content.addView(mLoadingView); + + mLoadingView.addObserver(mTestObserver1); + mLoadingView.addObserver(mTestObserver2); + } + + @Test + @SmallTest + public void testLoadingFast() { + mLoadingView.showLoadingUI(); + Assert.assertEquals( + "showLoadingCallback1 should not be executed as soon as showLoadingUI is called.", + 0, mTestObserver1.showLoadingCallback.getCallCount()); + Assert.assertEquals( + "showLoadingCallback2 should not be executed as soon as showLoadingUI is called.", + 0, mTestObserver2.showLoadingCallback.getCallCount()); + + ShadowLooper.idleMainLooper(100, TimeUnit.MILLISECONDS); + Assert.assertEquals("Progress bar should be hidden before 500ms.", View.GONE, + mLoadingView.getVisibility()); + Assert.assertEquals("showLoadingCallback1 should not be executed with loading fast.", 0, + mTestObserver1.showLoadingCallback.getCallCount()); + Assert.assertEquals("showLoadingCallback2 should not be executed with loading fast.", 0, + mTestObserver2.showLoadingCallback.getCallCount()); + + mLoadingView.hideLoadingUI(); + Assert.assertEquals( + "Progress bar should never be visible.", View.GONE, mLoadingView.getVisibility()); + Assert.assertEquals("hideLoadingCallback1 should be executed after loading finishes.", 1, + mTestObserver1.hideLoadingCallback.getCallCount()); + Assert.assertEquals("hideLoadingCallback2 should be executed after loading finishes.", 1, + mTestObserver2.hideLoadingCallback.getCallCount()); + } + + @Test + @SmallTest + public void testLoadingSlow() { + long sleepTime = 500; + mLoadingView.showLoadingUI(); + Assert.assertEquals( + "showLoadingCallback1 should not be executed as soon as showLoadingUI is called.", + 0, mTestObserver1.showLoadingCallback.getCallCount()); + Assert.assertEquals( + "showLoadingCallback2 should not be executed as soon as showLoadingUI is called.", + 0, mTestObserver2.showLoadingCallback.getCallCount()); + + ShadowLooper.idleMainLooper(sleepTime, TimeUnit.MILLISECONDS); + Assert.assertEquals("Progress bar should be visible after 500ms.", View.VISIBLE, + mLoadingView.getVisibility()); + Assert.assertEquals("showLoadingCallback1 should be executed when spinner is visible.", 1, + mTestObserver1.showLoadingCallback.getCallCount()); + Assert.assertEquals("showLoadingCallback2 should be executed when spinner is visible.", 1, + mTestObserver2.showLoadingCallback.getCallCount()); + + mLoadingView.hideLoadingUI(); + Assert.assertEquals("Progress bar should still be visible until showing for 500ms.", + View.VISIBLE, mLoadingView.getVisibility()); + Assert.assertEquals("hideLoadingCallback1 should not be executed before loading finishes.", + 0, mTestObserver1.hideLoadingCallback.getCallCount()); + Assert.assertEquals("hideLoadingCallback2 should not be executed before loading finishes.", + 0, mTestObserver2.hideLoadingCallback.getCallCount()); + + // The spinner should be displayed for at least 500ms. + ShadowLooper.idleMainLooper(sleepTime, TimeUnit.MILLISECONDS); + Assert.assertEquals("Progress bar should be hidden after 500ms.", View.GONE, + mLoadingView.getVisibility()); + Assert.assertEquals("hideLoadingCallback1 should be executed after loading finishes.", 1, + mTestObserver1.hideLoadingCallback.getCallCount()); + Assert.assertEquals("hideLoadingCallback2 should be executed after loading finishes.", 1, + mTestObserver2.hideLoadingCallback.getCallCount()); + } +} diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn index 22d0ec9dd4d..f638d50067f 100644 --- a/chromium/ui/aura/BUILD.gn +++ b/chromium/ui/aura/BUILD.gn @@ -134,6 +134,7 @@ component("aura") { public_deps = [ "//ui/base/cursor:cursor_base", + "//ui/base/dragdrop:types", "//ui/base/dragdrop/mojom:mojom_headers", "//ui/base/ime", "//ui/compositor", @@ -374,6 +375,11 @@ test("aura_unittests") { deps += [ "//ui/ozone" ] } + if (is_fuchsia) { + additional_manifest_fragments = + [ "//build/config/fuchsia/test/present_view_capabilities.test-cmx" ] + } + data_deps = [ "//third_party/mesa_headers" ] } diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc index ac740522a77..e1d88b353f8 100644 --- a/chromium/ui/aura/client/aura_constants.cc +++ b/chromium/ui/aura/client/aura_constants.cc @@ -10,7 +10,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, bool) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::TimeDelta) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::UnguessableToken*) -DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::string16*) +DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, std::u16string*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ModalType) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ZOrderLevel) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::ImageSkia*) @@ -70,7 +70,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(ui::WindowShowState, kShowStateKey, ui::SHOW_STATE_DEFAULT) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSkipImeProcessing, false) -DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(base::string16, kTitleKey, nullptr) +DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::u16string, kTitleKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(int, kTopViewInset, 0) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kVisibleOnAllWorkspacesKey, false) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kWindowIconKey, nullptr) diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h index ac15d1b3519..c81a0263bee 100644 --- a/chromium/ui/aura/client/aura_constants.h +++ b/chromium/ui/aura/client/aura_constants.h @@ -8,7 +8,6 @@ #include #include -#include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/aura_export.h" #include "ui/aura/window.h" @@ -140,7 +139,7 @@ AURA_EXPORT extern const WindowProperty* const AURA_EXPORT extern const WindowProperty* const kSkipImeProcessing; // A property key to store the title of the window; sometimes shown to users. -AURA_EXPORT extern const WindowProperty* const kTitleKey; +AURA_EXPORT extern const WindowProperty* const kTitleKey; // The inset of the topmost view in the client view from the top of the // non-client view. The topmost view depends on the window type. The topmost diff --git a/chromium/ui/aura/client/cursor_client.h b/chromium/ui/aura/client/cursor_client.h index 076ec1ab8bb..a39aeff5870 100644 --- a/chromium/ui/aura/client/cursor_client.h +++ b/chromium/ui/aura/client/cursor_client.h @@ -5,7 +5,8 @@ #ifndef UI_AURA_CLIENT_CURSOR_CLIENT_H_ #define UI_AURA_CLIENT_CURSOR_CLIENT_H_ -#include "base/strings/string16.h" +#include + #include "ui/aura/aura_export.h" #include "ui/base/cursor/cursor.h" #include "ui/gfx/native_widget_types.h" diff --git a/chromium/ui/aura/client/drag_drop_client_observer.h b/chromium/ui/aura/client/drag_drop_client_observer.h index f668f77cb86..1f353d794ae 100644 --- a/chromium/ui/aura/client/drag_drop_client_observer.h +++ b/chromium/ui/aura/client/drag_drop_client_observer.h @@ -8,16 +8,25 @@ #include "build/chromeos_buildflags.h" #include "ui/aura/aura_export.h" +namespace ui { +class DropTargetEvent; +} // namespace ui + namespace aura { namespace client { class AURA_EXPORT DragDropClientObserver { public: + virtual ~DragDropClientObserver() = default; + // Called when dragging started. - virtual void OnDragStarted() = 0; + virtual void OnDragStarted() {} + + // Called when dragging is updated. + virtual void OnDragUpdated(const ui::DropTargetEvent& event) {} // Called when dragging ended. - virtual void OnDragEnded() = 0; + virtual void OnDragEnded() {} #if BUILDFLAG(IS_CHROMEOS_ASH) // Called when the set of currently selected drag operation changes during the @@ -26,9 +35,6 @@ class AURA_EXPORT DragDropClientObserver { // the operation returned from StartDragAndDrop. virtual void OnDragActionsChanged(int actions) {} #endif - - protected: - virtual ~DragDropClientObserver() = default; }; } // namespace client diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc index 1aa181ecd8d..043a669ebea 100644 --- a/chromium/ui/aura/env.cc +++ b/chromium/ui/aura/env.cc @@ -165,20 +165,11 @@ WindowOcclusionTracker* Env::GetWindowOcclusionTracker() { } void Env::PauseWindowOcclusionTracking() { - const bool was_paused = GetWindowOcclusionTracker(); GetWindowOcclusionTracker()->Pause(); - if (!was_paused) { - for (EnvObserver& observer : observers_) - observer.OnWindowOcclusionTrackingPaused(); - } } void Env::UnpauseWindowOcclusionTracking() { GetWindowOcclusionTracker()->Unpause(); - if (!GetWindowOcclusionTracker()->IsPaused()) { - for (EnvObserver& observer : observers_) - observer.OnWindowOcclusionTrackingResumed(); - } } void Env::AddEventObserver(ui::EventObserver* observer, diff --git a/chromium/ui/aura/env_observer.h b/chromium/ui/aura/env_observer.h index e9a3e7870aa..5d571fd6952 100644 --- a/chromium/ui/aura/env_observer.h +++ b/chromium/ui/aura/env_observer.h @@ -26,11 +26,6 @@ class AURA_EXPORT EnvObserver { // Called right before Env is destroyed. virtual void OnWillDestroyEnv() {} - // Called when occlusion tracker pauses/resumes. This is only called in - // Mode::LOCAL. - virtual void OnWindowOcclusionTrackingPaused() {} - virtual void OnWindowOcclusionTrackingResumed() {} - protected: virtual ~EnvObserver() {} }; diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.cc b/chromium/ui/aura/native_window_occlusion_tracker_win.cc index ac50a5b093f..57f85d3699f 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win.cc +++ b/chromium/ui/aura/native_window_occlusion_tracker_win.cc @@ -22,7 +22,9 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/win/scoped_gdi_object.h" #include "base/win/windows_version.h" +#include "ui/aura/window_occlusion_tracker.h" #include "ui/aura/window_tree_host.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/win/hwnd_util.h" namespace aura { @@ -243,6 +245,9 @@ void NativeWindowOcclusionTrackerWin::UpdateOcclusionState( const base::flat_map& root_window_hwnds_occlusion_state, bool show_all_windows) { + // Pause occlusion until we've updated all root windows, to avoid O(n^3) + // calls to recompute occlusion in WindowOcclusionTracker. + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking; num_visible_root_windows_ = 0; for (const auto& root_window_pair : root_window_hwnds_occlusion_state) { auto it = hwnd_root_window_map_.find(root_window_pair.first); @@ -287,14 +292,28 @@ void NativeWindowOcclusionTrackerWin::OnSessionChange( } void NativeWindowOcclusionTrackerWin::OnDisplayStateChanged(bool display_on) { + static bool screen_power_listener_enabled = base::FeatureList::IsEnabled( + features::kScreenPowerListenerForNativeWinOcclusion); + if (!screen_power_listener_enabled) + return; + if (display_on == display_on_) return; display_on_ = display_on; - // Display changing to on will cause a foreground window change, - // which will trigger an occlusion calculation on its own. - if (!display_on_) + if (display_on_) { + // Notify the window occlusion calculator of the display turning on + // which will schedule an occlusion calculation. This must be run + // on the WindowOcclusionCalculator thread. + update_occlusion_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &WindowOcclusionCalculator::HandleVisibilityChanged, + base::Unretained(WindowOcclusionCalculator::GetInstance()), + /*visible=*/true)); + } else { MarkNonIconicWindowsOccluded(); + } } void NativeWindowOcclusionTrackerWin::MarkNonIconicWindowsOccluded() { @@ -700,8 +719,8 @@ void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator:: FROM_HERE, base::BindOnce(update_occlusion_state_callback_, root_window_hwnds_occlusion_state_, showing_thumbnails_)); - return; } + return; } else if (event == EVENT_OBJECT_HIDE) { // Avoid getting the hwnd's class name, and recomputing occlusion, if not // needed. @@ -714,6 +733,8 @@ void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator:: // Let occlusion calculation fix occlusion state, even though hwnd might // be a popup window. calculate_occlusion = true; + } else { + return; } } // Don't continually calculate occlusion while a window is moving (unless it's diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.h b/chromium/ui/aura/native_window_occlusion_tracker_win.h index 4934e8b3175..b1a44a9989b 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win.h +++ b/chromium/ui/aura/native_window_occlusion_tracker_win.h @@ -63,7 +63,8 @@ class AURA_EXPORT NativeWindowOcclusionTrackerWin private: friend class NativeWindowOcclusionTrackerTest; - + FRIEND_TEST_ALL_PREFIXES(NativeWindowOcclusionTrackerTest, + DisplayOnOffHandling); // This class computes the occlusion state of the tracked windows. // It runs on a separate thread, and notifies the main thread of // the occlusion state of the tracked windows. diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc b/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc index 197f1961555..f86003a2970 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc +++ b/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc @@ -400,4 +400,36 @@ TEST_F(NativeWindowOcclusionTrackerTest, LockScreenDifferentSession) { host()->RemoveObserver(&observer); } +// Test that display off & on power state notification causes visible windows to +// become occluded, then visible. +TEST_F(NativeWindowOcclusionTrackerTest, DisplayOnOffHandling) { + base::RunLoop run_loop; + + MockWindowTreeHostObserver observer(run_loop.QuitClosure()); + CreateTrackedAuraWindowWithBounds(&observer, gfx::Rect(0, 0, 100, 100)); + observer.set_expectation(Window::OcclusionState::VISIBLE); + run_loop.Run(); + EXPECT_FALSE(observer.is_expecting_call()); + + NativeWindowOcclusionTrackerWin* occlusion_tracker = + NativeWindowOcclusionTrackerWin::GetOrCreateInstance(); + + observer.set_expectation(Window::OcclusionState::OCCLUDED); + base::RunLoop run_loop2; + observer.set_quit_closure(run_loop2.QuitClosure()); + + // Turning display off and on isn't feasible, so send a notification. + occlusion_tracker->OnDisplayStateChanged(/*display_on=*/false); + run_loop2.Run(); + EXPECT_FALSE(observer.is_expecting_call()); + + observer.set_expectation(Window::OcclusionState::VISIBLE); + base::RunLoop run_loop3; + observer.set_quit_closure(run_loop3.QuitClosure()); + occlusion_tracker->OnDisplayStateChanged(/*display_on=*/true); + run_loop3.Run(); + EXPECT_FALSE(observer.is_expecting_call()); + host()->RemoveObserver(&observer); +} + } // namespace aura diff --git a/chromium/ui/aura/screen_ozone.h b/chromium/ui/aura/screen_ozone.h index f92c14f5667..b989f378a23 100644 --- a/chromium/ui/aura/screen_ozone.h +++ b/chromium/ui/aura/screen_ozone.h @@ -54,6 +54,9 @@ class AURA_EXPORT ScreenOzone : public display::Screen { virtual gfx::NativeWindow GetNativeWindowFromAcceleratedWidget( gfx::AcceleratedWidget widget) const; + protected: + ui::PlatformScreen* platform_screen() { return platform_screen_.get(); } + private: gfx::AcceleratedWidget GetAcceleratedWidgetForWindow( aura::Window* window) const; diff --git a/chromium/ui/aura/test/ui_controls_ozone.cc b/chromium/ui/aura/test/ui_controls_ozone.cc index 2572a3c2f14..965b6abfa88 100644 --- a/chromium/ui/aura/test/ui_controls_ozone.cc +++ b/chromium/ui/aura/test/ui_controls_ozone.cc @@ -6,6 +6,7 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "ui/events/event_utils.h" namespace aura { namespace test { @@ -275,6 +276,15 @@ void UIControlsOzone::PostKeyEventTask(ui::EventType type, flags |= ui::EF_FINAL; ui::KeyEvent key_event(type, key_code, flags); + if (type == ui::ET_KEY_PRESSED) { + // Set a property as if this is a key event not consumed by IME. + // Ozone/X11+GTK IME works so already. Ozone/wayland IME relies on this + // flag to work properly. + key_event.SetProperties({{ + ui::kPropertyKeyboardImeFlag, + std::vector{ui::kPropertyKeyboardImeIgnoredFlag}, + }}); + } SendEventToSink(&key_event, display_id, std::move(closure), optional_host); } diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index 283092e62f2..303a0290b53 100644 --- a/chromium/ui/aura/window.cc +++ b/chromium/ui/aura/window.cc @@ -217,12 +217,12 @@ void Window::SetName(const std::string& name) { UpdateLayerName(); } -const base::string16& Window::GetTitle() const { - base::string16* title = GetProperty(client::kTitleKey); +const std::u16string& Window::GetTitle() const { + std::u16string* title = GetProperty(client::kTitleKey); return title ? *title : base::EmptyString16(); } -void Window::SetTitle(const base::string16& title) { +void Window::SetTitle(const std::u16string& title) { if (title == GetTitle()) return; SetProperty(client::kTitleKey, title); diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h index b422c18d087..d3034469851 100644 --- a/chromium/ui/aura/window.h +++ b/chromium/ui/aura/window.h @@ -20,7 +20,6 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/viz/common/surfaces/frame_sink_id.h" @@ -173,8 +172,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate, const std::string& GetName() const; void SetName(const std::string& name); - const base::string16& GetTitle() const; - void SetTitle(const base::string16& title); + const std::u16string& GetTitle() const; + void SetTitle(const std::u16string& title); bool transparent() const { return transparent_; } diff --git a/chromium/ui/aura/window_observer.h b/chromium/ui/aura/window_observer.h index 4c34dbe7a12..c2ce7a6d141 100644 --- a/chromium/ui/aura/window_observer.h +++ b/chromium/ui/aura/window_observer.h @@ -5,8 +5,9 @@ #ifndef UI_AURA_WINDOW_OBSERVER_H_ #define UI_AURA_WINDOW_OBSERVER_H_ +#include + #include "base/observer_list_types.h" -#include "base/strings/string16.h" #include "ui/aura/aura_export.h" #include "ui/compositor/property_change_reason.h" diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc index 7589542026f..6025626d122 100644 --- a/chromium/ui/aura/window_tree_host_platform.cc +++ b/chromium/ui/aura/window_tree_host_platform.cc @@ -202,7 +202,7 @@ void WindowTreeHostPlatform::OnCursorVisibilityChangedNative(bool show) { NOTIMPLEMENTED(); } -void WindowTreeHostPlatform::OnBoundsChanged(const gfx::Rect& new_bounds) { +void WindowTreeHostPlatform::OnBoundsChanged(const BoundsChange& change) { // It's possible this function may be called recursively. Only notify // observers on initial entry. This way observers can safely assume that // OnHostDidProcessBoundsChange() is called when all bounds changes have @@ -215,7 +215,7 @@ void WindowTreeHostPlatform::OnBoundsChanged(const gfx::Rect& new_bounds) { float new_scale = ui::GetScaleFactorForNativeView(window()); gfx::Rect old_bounds = bounds_in_pixels_; auto weak_ref = GetWeakPtr(); - bounds_in_pixels_ = new_bounds; + bounds_in_pixels_ = change.bounds; if (bounds_in_pixels_.origin() != old_bounds.origin()) { OnHostMovedInPixels(bounds_in_pixels_.origin()); // Changing the bounds may destroy this. diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h index 27d7d78a34a..60d5129bdb9 100644 --- a/chromium/ui/aura/window_tree_host_platform.h +++ b/chromium/ui/aura/window_tree_host_platform.h @@ -66,7 +66,7 @@ class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost, void SetPlatformWindow(std::unique_ptr window); // ui::PlatformWindowDelegate: - void OnBoundsChanged(const gfx::Rect& new_bounds) override; + void OnBoundsChanged(const BoundsChange& change) override; void OnDamageRect(const gfx::Rect& damaged_region) override; void DispatchEvent(ui::Event* event) override; void OnCloseRequest() override; diff --git a/chromium/ui/aura_extra/image_window_delegate.cc b/chromium/ui/aura_extra/image_window_delegate.cc index ac8db1057be..58fa8becb1b 100644 --- a/chromium/ui/aura_extra/image_window_delegate.cc +++ b/chromium/ui/aura_extra/image_window_delegate.cc @@ -16,13 +16,9 @@ namespace aura_extra { -ImageWindowDelegate::ImageWindowDelegate() - : background_color_(SK_ColorWHITE), - size_mismatch_(false) { -} +ImageWindowDelegate::ImageWindowDelegate() = default; -ImageWindowDelegate::~ImageWindowDelegate() { -} +ImageWindowDelegate::~ImageWindowDelegate() = default; void ImageWindowDelegate::SetImage(const gfx::Image& image) { image_ = image; diff --git a/chromium/ui/aura_extra/image_window_delegate.h b/chromium/ui/aura_extra/image_window_delegate.h index 09c34b23ba5..0b1f3ad2943 100644 --- a/chromium/ui/aura_extra/image_window_delegate.h +++ b/chromium/ui/aura_extra/image_window_delegate.h @@ -5,7 +5,6 @@ #ifndef UI_AURA_EXTRA_IMAGE_WINDOW_DELEGATE_H_ #define UI_AURA_EXTRA_IMAGE_WINDOW_DELEGATE_H_ -#include "base/macros.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/window_delegate.h" #include "ui/aura_extra/aura_extra_export.h" @@ -15,9 +14,9 @@ namespace aura_extra { -// An ImageWindowDelegate paints an image for a Window, possibly also filling -// the window with a specified backround color. The delegate does not consume -// any event. +// An ImageWindowDelegate paints an image for a Window. If there is uncovered +// area, it also fills the window with a background color when specified. +// The delegate does not consume any event. // // The delegate destroys itself when the Window is destroyed. This is done in // |OnWindowDestroyed()| function which subclasses can override to prevent @@ -25,6 +24,8 @@ namespace aura_extra { class AURA_EXTRA_EXPORT ImageWindowDelegate : public aura::WindowDelegate { public: ImageWindowDelegate(); + ImageWindowDelegate(const ImageWindowDelegate&) = delete; + ImageWindowDelegate& operator=(const ImageWindowDelegate&) = delete; void SetImage(const gfx::Image& image); @@ -58,7 +59,7 @@ class AURA_EXTRA_EXPORT ImageWindowDelegate : public aura::WindowDelegate { void GetHitTestMask(SkPath* mask) const override; protected: - SkColor background_color_; + SkColor background_color_ = SK_ColorTRANSPARENT; gfx::Image image_; gfx::Vector2d offset_; @@ -66,10 +67,8 @@ class AURA_EXTRA_EXPORT ImageWindowDelegate : public aura::WindowDelegate { // Keeps track of whether the window size matches the image size or not. If // the image size is smaller than the window size, then the delegate fills the - // missing regions with |background_color_| (defult is white). - bool size_mismatch_; - - DISALLOW_COPY_AND_ASSIGN(ImageWindowDelegate); + // missing regions with |background_color_| (default is transparent). + bool size_mismatch_ = false; }; } // namespace aura_extra diff --git a/chromium/ui/base/BUILD.gn b/chromium/ui/base/BUILD.gn index b88df58d50b..d26e454c8ed 100644 --- a/chromium/ui/base/BUILD.gn +++ b/chromium/ui/base/BUILD.gn @@ -81,6 +81,8 @@ source_set("hit_test") { "hit_test_x11.h", ] } + + deps = [ "//base" ] } component("base") { @@ -92,8 +94,6 @@ component("base") { "default_style.h", "device_form_factor.h", "device_form_factor_desktop.cc", - "dragdrop/drag_drop_types.cc", - "dragdrop/drag_drop_types.h", "dragdrop/drop_target_event.cc", "dragdrop/drop_target_event.h", "dragdrop/os_exchange_data.cc", @@ -193,7 +193,6 @@ component("base") { if (is_win) { sources += [ - "dragdrop/drag_drop_types_win.cc", "dragdrop/drag_source_win.cc", "dragdrop/drag_source_win.h", "dragdrop/drop_target_win.cc", @@ -307,7 +306,6 @@ component("base") { "cocoa/weak_ptr_nsobject.mm", "cocoa/window_size_constants.h", "cocoa/window_size_constants.mm", - "dragdrop/drag_drop_types_mac.mm", "dragdrop/os_exchange_data_provider_builder_mac.h", "dragdrop/os_exchange_data_provider_builder_mac.mm", "dragdrop/os_exchange_data_provider_mac.h", @@ -329,8 +327,6 @@ component("base") { sources += [ "accelerators/accelerator.cc", "accelerators/accelerator.h", - "accelerators/accelerator_history.cc", - "accelerators/accelerator_history.h", "accelerators/accelerator_manager.cc", "accelerators/accelerator_manager.h", "accelerators/media_keys_listener.cc", @@ -359,6 +355,8 @@ component("base") { sources += [ "accelerators/menu_label_accelerator_util_linux.cc", "accelerators/menu_label_accelerator_util_linux.h", + "linux/linux_desktop.cc", + "linux/linux_desktop.h", ] } @@ -496,23 +494,16 @@ component("base") { } } - if (use_x11 && use_aura) { + if (use_x11 && use_aura && is_linux) { + # These Aura X11 files aren't used on ChromeOS. sources += [ - "x/selection_requestor.cc", - "x/selection_requestor.h", + "dragdrop/os_exchange_data_provider_x11.cc", + "dragdrop/os_exchange_data_provider_x11.h", ] deps += [ "//ui/events/platform/x11", "//ui/gfx/x", ] - - if (!is_chromeos_ash) { - # These Aura X11 files aren't used on ChromeOS. - sources += [ - "dragdrop/os_exchange_data_provider_x11.cc", - "dragdrop/os_exchange_data_provider_x11.h", - ] - } } if (use_aura && (is_linux || is_chromeos)) { @@ -526,6 +517,7 @@ component("base") { if (use_glib) { configs += [ "//build/config/linux:glib" ] sources += [ + "glib/glib_cast.h", "glib/glib_integers.h", "glib/glib_signal.h", "glib/scoped_gobject.h", @@ -566,8 +558,6 @@ component("base") { if (!toolkit_views && !use_aura) { sources -= [ - "dragdrop/drag_drop_types.cc", - "dragdrop/drag_drop_types.h", "dragdrop/drop_target_event.cc", "dragdrop/drop_target_event.h", "dragdrop/os_exchange_data.cc", @@ -975,7 +965,6 @@ test("ui_base_unittests") { ] } else { # !is_ios sources += [ - "accelerators/accelerator_history_unittest.cc", "accelerators/accelerator_manager_unittest.cc", "accelerators/accelerator_unittest.cc", "accelerators/menu_label_accelerator_util_unittest.cc", @@ -1133,7 +1122,6 @@ test("ui_base_unittests") { # TODO(crbug.com/980371): Implement OSExchangeDataProvider for Fuchsia. if ((use_aura || toolkit_views) && !is_fuchsia) { sources += [ "dragdrop/os_exchange_data_unittest.cc" ] - deps += [ "//ui/events", "//ui/events/platform", @@ -1141,10 +1129,7 @@ test("ui_base_unittests") { } if (use_x11) { - sources += [ - "dragdrop/os_exchange_data_provider_x11_unittest.cc", - "x/selection_requestor_unittest.cc", - ] + sources += [ "dragdrop/os_exchange_data_provider_x11_unittest.cc" ] deps += [ "//ui/gfx/x:unit_test" ] } diff --git a/chromium/ui/base/OWNERS b/chromium/ui/base/OWNERS index 01f524d676f..636b5c77c90 100644 --- a/chromium/ui/base/OWNERS +++ b/chromium/ui/base/OWNERS @@ -1,3 +1,5 @@ +pbos@chromium.org + per-file template_expressions*=dpapad@chromium.org per-file template_expressions*=michaelpg@chromium.org per-file template_expressions*=rbpotter@chromium.org diff --git a/chromium/ui/base/accelerators/accelerator.cc b/chromium/ui/base/accelerators/accelerator.cc index 17e1739c12e..c44f3d37520 100644 --- a/chromium/ui/base/accelerators/accelerator.cc +++ b/chromium/ui/base/accelerators/accelerator.cc @@ -10,7 +10,6 @@ #include "base/check_op.h" #include "base/i18n/rtl.h" #include "base/notreached.h" -#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -20,11 +19,15 @@ #include "ui/events/keycodes/keyboard_code_conversion.h" #include "ui/strings/grit/ui_strings.h" +#if defined(OS_MAC) +#include "base/mac/mac_util.h" +#endif + #if defined(OS_WIN) #include #endif -#if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_APPLE)) +#if !defined(OS_WIN) && (defined(USE_AURA) || defined(OS_MAC)) #include "ui/events/keycodes/keyboard_code_conversion.h" #endif @@ -83,8 +86,8 @@ const int kModifierMask = EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN | const int kInterestingFlagsMask = kModifierMask | EF_IS_SYNTHESIZED | EF_IS_REPEAT; -base::string16 ApplyModifierToAcceleratorString( - const base::string16& accelerator, +std::u16string ApplyModifierToAcceleratorString( + const std::u16string& accelerator, int modifier_message_id) { return l10n_util::GetStringFUTF16( IDS_APP_ACCELERATOR_WITH_MODIFIER, @@ -154,21 +157,21 @@ KeyEvent Accelerator::ToKeyEvent() const { key_code(), modifiers(), time_stamp()); } -bool Accelerator::operator <(const Accelerator& rhs) const { +bool Accelerator::operator<(const Accelerator& rhs) const { const int modifiers_with_mask = MaskOutKeyEventFlags(modifiers_); const int rhs_modifiers_with_mask = MaskOutKeyEventFlags(rhs.modifiers_); return std::tie(key_code_, key_state_, modifiers_with_mask) < std::tie(rhs.key_code_, rhs.key_state_, rhs_modifiers_with_mask); } -bool Accelerator::operator ==(const Accelerator& rhs) const { +bool Accelerator::operator==(const Accelerator& rhs) const { return (key_code_ == rhs.key_code_) && (key_state_ == rhs.key_state_) && (MaskOutKeyEventFlags(modifiers_) == MaskOutKeyEventFlags(rhs.modifiers_)) && interrupted_by_mouse_event_ == rhs.interrupted_by_mouse_event_; } -bool Accelerator::operator !=(const Accelerator& rhs) const { +bool Accelerator::operator!=(const Accelerator& rhs) const { return !(*this == rhs); } @@ -196,10 +199,10 @@ bool Accelerator::IsRepeat() const { return (modifiers_ & EF_IS_REPEAT) != 0; } -base::string16 Accelerator::GetShortcutText() const { - base::string16 shortcut; +std::u16string Accelerator::GetShortcutText() const { + std::u16string shortcut; -#if defined(OS_APPLE) +#if defined(OS_MAC) shortcut = KeyCodeToMacSymbol(); #else shortcut = KeyCodeToName(); @@ -222,23 +225,23 @@ base::string16 Accelerator::GetShortcutText() const { // VKEY_UNKNOWN), |::MapVirtualKeyW| returns 0. if (key != 0) shortcut += key; -#elif defined(USE_AURA) || defined(OS_APPLE) || defined(OS_ANDROID) +#elif defined(USE_AURA) || defined(OS_MAC) || defined(OS_ANDROID) const uint16_t c = DomCodeToUsLayoutCharacter( UsLayoutKeyboardCodeToDomCode(key_code_), false); if (c != 0) shortcut += - static_cast(base::ToUpperASCII(c)); + static_cast(base::ToUpperASCII(c)); #endif } -#if defined(OS_APPLE) +#if defined(OS_MAC) shortcut = ApplyShortFormModifiers(shortcut); #else // Checking whether the character used for the accelerator is alphanumeric. // If it is not, then we need to adjust the string later on if the locale is // right-to-left. See below for more information of why such adjustment is // required. - base::string16 shortcut_rtl; + std::u16string shortcut_rtl; bool adjust_shortcut_for_rtl = false; if (base::i18n::IsRTL() && shortcut.length() == 1 && !base::IsAsciiAlpha(shortcut[0]) && !base::IsAsciiDigit(shortcut[0])) { @@ -264,63 +267,74 @@ base::string16 Accelerator::GetShortcutText() const { // RTL context because the punctuation no longer appears at the end of the // string. // - // TODO(idana) bug# 1232732: this hack can be avoided if instead of using - // views::Menu we use views::MenuItemView because the latter is a View - // subclass and therefore it supports marking text as RTL or LTR using - // standard Unicode directionality marks. + // TODO(crbug.com/1194340): This hack of doing the RTL adjustment here was + // intended to be removed when the menu system moved to MenuItemView. That was + // crbug.com/2822, closed in 2010. Can we finally remove all of this? if (adjust_shortcut_for_rtl) { int key_length = static_cast(shortcut_rtl.length()); DCHECK_GT(key_length, 0); - shortcut_rtl.append(base::ASCIIToUTF16("+")); + shortcut_rtl.append(u"+"); // Subtracting the size of the shortcut key and 1 for the '+' sign. shortcut_rtl.append(shortcut, 0, shortcut.length() - key_length - 1); shortcut.swap(shortcut_rtl); } -#endif // OS_APPLE +#endif // OS_MAC return shortcut; } -#if defined(OS_APPLE) -base::string16 Accelerator::KeyCodeToMacSymbol() const { +#if defined(OS_MAC) +// In macOS 10.13, the glyphs used for page up, page down, home, and end were +// changed from the arrows below to new, skinny arrows. The tricky bit is that +// the underlying Unicode characters weren't changed, just the font used. Maybe +// the keyboard font, CTFontCreateUIFontForLanguage, with key +// kCTFontUIFontMenuItemCmdKey, can be used everywhere this symbol is used. (If +// so, then the RTL stuff will need to be removed.) +std::u16string Accelerator::KeyCodeToMacSymbol() const { switch (key_code_) { case VKEY_CAPITAL: - return base::string16({0x21ea}); + return u"⇪"; // U+21EA, UPWARDS WHITE ARROW FROM BAR case VKEY_RETURN: - return base::string16({0x2324}); + return u"⌤"; // U+2324, UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS case VKEY_BACK: - return base::string16({0x232b}); + return u"⌫"; // U+232B, ERASE TO THE LEFT case VKEY_ESCAPE: - return base::string16({0x238b}); + return u"⎋"; // U+238B, BROKEN CIRCLE WITH NORTHWEST ARROW case VKEY_RIGHT: - return base::string16({0x2192}); + return u"→"; // U+2192, RIGHTWARDS ARROW case VKEY_LEFT: - return base::string16({0x2190}); + return u"←"; // U+2190, LEFTWARDS ARROW case VKEY_UP: - return base::string16({0x2191}); + return u"↑"; // U+2191, UPWARDS ARROW case VKEY_DOWN: - return base::string16({0x2193}); + return u"↓"; // U+2193, DOWNWARDS ARROW case VKEY_PRIOR: - return base::string16({0x21de}); + return u"⇞"; // U+21DE, UPWARDS ARROW WITH DOUBLE STROKE case VKEY_NEXT: - return base::string16({0x21df}); + return u"⇟"; // U+21DF, DOWNWARDS ARROW WITH DOUBLE STROKE case VKEY_HOME: - return base::string16({0x2196}); + if (base::mac::IsAtLeastOS10_13() && base::i18n::IsRTL()) { + return u"↗"; // U+2197, NORTH EAST ARROW + } + return u"↖"; // U+2196, NORTH WEST ARROW case VKEY_END: - return base::string16({0x2198}); + if (base::mac::IsAtLeastOS10_13() && base::i18n::IsRTL()) { + return u"↙"; // U+2199, SOUTH WEST ARROW + } + return u"↘"; // U+2198, SOUTH EAST ARROW case VKEY_TAB: - return base::string16({0x21e5}); - // Mac has a shift-tab icon (0x21e4) but we don't use it. - // "Space" and some other keys are written out; fall back to KeyCodeToName() - // for those (and any other unhandled keys). + return u"⇥"; // U+21E5, RIGHTWARDS ARROW TO BAR + // Mac has a shift-tab icon ("⇤", U+21E4, LEFTWARDS ARROW TO BAR) but we + // don't use it. "Space" and some other keys are written out; fall back to + // KeyCodeToName() for those (and any other unhandled keys). default: return KeyCodeToName(); } } -#endif // OS_APPLE +#endif // OS_MAC -base::string16 Accelerator::KeyCodeToName() const { +std::u16string Accelerator::KeyCodeToName() const { int string_id = 0; switch (key_code_) { case VKEY_TAB: @@ -374,7 +388,7 @@ base::string16 Accelerator::KeyCodeToName() const { case VKEY_F11: string_id = IDS_APP_F11_KEY; break; -#if !defined(OS_APPLE) +#if !defined(OS_MAC) // On Mac, commas and periods are used literally in accelerator text. case VKEY_OEM_COMMA: string_id = IDS_APP_COMMA_KEY; @@ -398,52 +412,56 @@ base::string16 Accelerator::KeyCodeToName() const { default: break; } - return string_id ? l10n_util::GetStringUTF16(string_id) : base::string16(); + return string_id ? l10n_util::GetStringUTF16(string_id) : std::u16string(); } -base::string16 Accelerator::ApplyLongFormModifiers( - base::string16 shortcut) const { +std::u16string Accelerator::ApplyLongFormModifiers( + const std::u16string& shortcut) const { + std::u16string result = shortcut; + if (IsShiftDown()) - shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_SHIFT_KEY); + result = ApplyModifierToAcceleratorString(result, IDS_APP_SHIFT_KEY); // Note that we use 'else-if' in order to avoid using Ctrl+Alt as a shortcut. // See http://blogs.msdn.com/oldnewthing/archive/2004/03/29/101121.aspx for // more information. if (IsCtrlDown()) - shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_CTRL_KEY); + result = ApplyModifierToAcceleratorString(result, IDS_APP_CTRL_KEY); else if (IsAltDown()) - shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_ALT_KEY); + result = ApplyModifierToAcceleratorString(result, IDS_APP_ALT_KEY); if (IsCmdDown()) { -#if defined(OS_APPLE) - shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_COMMAND_KEY); +#if defined(OS_MAC) + result = ApplyModifierToAcceleratorString(result, IDS_APP_COMMAND_KEY); #elif BUILDFLAG(IS_CHROMEOS_ASH) - shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_SEARCH_KEY); + result = ApplyModifierToAcceleratorString(result, IDS_APP_SEARCH_KEY); #elif defined(OS_WIN) - shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_WINDOWS_KEY); + result = ApplyModifierToAcceleratorString(result, IDS_APP_WINDOWS_KEY); #else NOTREACHED(); #endif } - return shortcut; + return result; } -base::string16 Accelerator::ApplyShortFormModifiers( - base::string16 shortcut) const { - const base::char16 kCommandSymbol[] = {0x2318, 0}; - const base::char16 kCtrlSymbol[] = {0x2303, 0}; - const base::char16 kShiftSymbol[] = {0x21e7, 0}; - const base::char16 kOptionSymbol[] = {0x2325, 0}; - const base::char16 kNoSymbol[] = {0}; - - std::vector parts; - parts.push_back(base::string16(IsCtrlDown() ? kCtrlSymbol : kNoSymbol)); - parts.push_back(base::string16(IsAltDown() ? kOptionSymbol : kNoSymbol)); - parts.push_back(base::string16(IsShiftDown() ? kShiftSymbol : kNoSymbol)); - parts.push_back(base::string16(IsCmdDown() ? kCommandSymbol : kNoSymbol)); - parts.push_back(shortcut); - return base::StrCat(parts); +std::u16string Accelerator::ApplyShortFormModifiers( + const std::u16string& shortcut) const { + std::u16string result; + result.reserve(6); + + if (IsCtrlDown()) + result.push_back(u'⌃'); // U+2303, UP ARROWHEAD + if (IsAltDown()) + result.push_back(u'⌥'); // U+2325, OPTION KEY + if (IsShiftDown()) + result.push_back(u'⇧'); // U+21E7, UPWARDS WHITE ARROW + if (IsCmdDown()) + result.push_back(u'⌘'); // U+2318, PLACE OF INTEREST SIGN + + result.append(shortcut); + + return result; } } // namespace ui diff --git a/chromium/ui/base/accelerators/accelerator.h b/chromium/ui/base/accelerators/accelerator.h index 35a9bb01aef..62eacbe23f9 100644 --- a/chromium/ui/base/accelerators/accelerator.h +++ b/chromium/ui/base/accelerators/accelerator.h @@ -12,10 +12,10 @@ #define UI_BASE_ACCELERATORS_ACCELERATOR_H_ #include +#include #include #include "base/component_export.h" -#include "base/strings/string16.h" #include "base/time/time.h" #include "build/build_config.h" #include "ui/events/event_constants.h" @@ -59,11 +59,11 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator { // Define the < operator so that the KeyboardShortcut can be used as a key in // a std::map. - bool operator <(const Accelerator& rhs) const; + bool operator<(const Accelerator& rhs) const; - bool operator ==(const Accelerator& rhs) const; + bool operator==(const Accelerator& rhs) const; - bool operator !=(const Accelerator& rhs) const; + bool operator!=(const Accelerator& rhs) const; KeyboardCode key_code() const { return key_code_; } @@ -85,12 +85,12 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator { bool IsRepeat() const; // Returns a string with the localized shortcut if any. - base::string16 GetShortcutText() const; + std::u16string GetShortcutText() const; -#if defined(OS_APPLE) - base::string16 KeyCodeToMacSymbol() const; +#if defined(OS_MAC) + std::u16string KeyCodeToMacSymbol() const; #endif - base::string16 KeyCodeToName() const; + std::u16string KeyCodeToName() const; void set_interrupted_by_mouse_event(bool interrupted_by_mouse_event) { interrupted_by_mouse_event_ = interrupted_by_mouse_event; @@ -101,8 +101,8 @@ class COMPONENT_EXPORT(UI_BASE) Accelerator { } private: - base::string16 ApplyLongFormModifiers(base::string16 shortcut) const; - base::string16 ApplyShortFormModifiers(base::string16 shortcut) const; + std::u16string ApplyLongFormModifiers(const std::u16string& shortcut) const; + std::u16string ApplyShortFormModifiers(const std::u16string& shortcut) const; // The keycode (VK_...). KeyboardCode key_code_; @@ -139,7 +139,7 @@ class COMPONENT_EXPORT(UI_BASE) AcceleratorTarget { virtual bool CanHandleAccelerators() const = 0; protected: - virtual ~AcceleratorTarget() {} + virtual ~AcceleratorTarget() = default; }; // Since accelerator code is one of the few things that can't be cross platform @@ -153,7 +153,7 @@ class AcceleratorProvider { Accelerator* accelerator) const = 0; protected: - virtual ~AcceleratorProvider() {} + virtual ~AcceleratorProvider() = default; }; } // namespace ui diff --git a/chromium/ui/base/accelerators/accelerator_history.cc b/chromium/ui/base/accelerators/accelerator_history.cc deleted file mode 100644 index 4438093c61b..00000000000 --- a/chromium/ui/base/accelerators/accelerator_history.cc +++ /dev/null @@ -1,91 +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/accelerators/accelerator_history.h" - -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "ui/events/event.h" -#include "ui/events/event_target.h" - -namespace ui { - -namespace { - -bool ShouldFilter(ui::KeyEvent* event) { - const ui::EventType type = event->type(); - if (!event->target() || - (type != ui::ET_KEY_PRESSED && type != ui::ET_KEY_RELEASED) || - event->is_char() || !event->target() || - // Key events with key code of VKEY_PROCESSKEY, usually created by virtual - // keyboard (like handwriting input), have no effect on accelerator and - // they may disturb the accelerator history. So filter them out. (see - // https://crbug.com/918317) - event->key_code() == ui::VKEY_PROCESSKEY) { - return true; - } - - return false; -} - -} // namespace - -AcceleratorHistory::AcceleratorHistory() = default; - -AcceleratorHistory::~AcceleratorHistory() = default; - -void AcceleratorHistory::OnKeyEvent(ui::KeyEvent* event) { - DCHECK(event->target()); - if (!ShouldFilter(event)) - StoreCurrentAccelerator(ui::Accelerator(*event)); -} - -void AcceleratorHistory::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() == ui::ET_MOUSE_PRESSED || - event->type() == ui::ET_MOUSE_RELEASED) { - InterruptCurrentAccelerator(); - } -} - -void AcceleratorHistory::StoreCurrentAccelerator( - const Accelerator& accelerator) { - // Track the currently pressed keys so that we don't mistakenly store an - // already pressed key as a new keypress after another key has been released. - // As an example, when the user presses and holds Alt+Search, then releases - // Alt but keeps holding the Search key down, at this point no new Search - // presses should be stored in the history after the Alt release, since Search - // was never released in the first place. crbug.com/704280. - if (accelerator.key_state() == Accelerator::KeyState::PRESSED) { - if (!currently_pressed_keys_.emplace(accelerator.key_code()).second) - return; - } else { - if (!currently_pressed_keys_.erase(accelerator.key_code())) { - // If the released accelerator doesn't have a corresponding press stored, - // likely the language was changed between press and release. Clear - // `currently_pressed_keys_` to prevent keys being left pressed. - std::string pressed_keys; - for (auto key_code : currently_pressed_keys_) - pressed_keys.append(base::NumberToString(key_code).append(" ")); - LOG(WARNING) << "Key Release (" << accelerator.key_code() - << ") delivered with no corresponding Press. " - "Clearing all pressed keys: " - << pressed_keys; - currently_pressed_keys_.clear(); - } - } - - if (accelerator != current_accelerator_) { - previous_accelerator_ = current_accelerator_; - current_accelerator_ = accelerator; - } -} - -void AcceleratorHistory::InterruptCurrentAccelerator() { - if (current_accelerator_.key_state() == Accelerator::KeyState::PRESSED) { - // Only interrupts pressed keys. - current_accelerator_.set_interrupted_by_mouse_event(true); - } -} - -} // namespace ui diff --git a/chromium/ui/base/accelerators/accelerator_history.h b/chromium/ui/base/accelerators/accelerator_history.h deleted file mode 100644 index f2600cfb3c8..00000000000 --- a/chromium/ui/base/accelerators/accelerator_history.h +++ /dev/null @@ -1,60 +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. - -#ifndef UI_BASE_ACCELERATORS_ACCELERATOR_HISTORY_H_ -#define UI_BASE_ACCELERATORS_ACCELERATOR_HISTORY_H_ - -#include - -#include "base/component_export.h" -#include "base/macros.h" -#include "ui/base/accelerators/accelerator.h" -#include "ui/events/event_handler.h" - -namespace ui { - -// Keeps track of the system-wide current and the most recent previous -// key accelerators. -class COMPONENT_EXPORT(UI_BASE) AcceleratorHistory : public ui::EventHandler { - public: - AcceleratorHistory(); - ~AcceleratorHistory() override; - - // Returns the most recent recorded accelerator. - const Accelerator& current_accelerator() const { - return current_accelerator_; - } - - // Returns the most recent previously recorded accelerator that is different - // than the current. - const Accelerator& previous_accelerator() const { - return previous_accelerator_; - } - - const std::set& currently_pressed_keys() const { - return currently_pressed_keys_; - } - - // ui::EventHandler: - void OnKeyEvent(ui::KeyEvent* event) override; - void OnMouseEvent(ui::MouseEvent* event) override; - - // Stores the given |accelerator| only if it's different than the currently - // stored one. - void StoreCurrentAccelerator(const Accelerator& accelerator); - - void InterruptCurrentAccelerator(); - - private: - Accelerator current_accelerator_; - Accelerator previous_accelerator_; - - std::set currently_pressed_keys_; - - DISALLOW_COPY_AND_ASSIGN(AcceleratorHistory); -}; - -} // namespace ui - -#endif // UI_BASE_ACCELERATORS_ACCELERATOR_HISTORY_H_ diff --git a/chromium/ui/base/accelerators/accelerator_history_unittest.cc b/chromium/ui/base/accelerators/accelerator_history_unittest.cc deleted file mode 100644 index b633fe34d56..00000000000 --- a/chromium/ui/base/accelerators/accelerator_history_unittest.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2017 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_history.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/accelerators/accelerator.h" - -namespace ui { - -TEST(AcceleratorHistoryTest, SimulatePressAndHold) { - AcceleratorHistory history; - Accelerator alt_press(ui::VKEY_MENU, ui::EF_NONE, - ui::Accelerator::KeyState::PRESSED); - history.StoreCurrentAccelerator(alt_press); - EXPECT_EQ(alt_press, history.current_accelerator()); - - // Repeats don't affect previous accelerators. - history.StoreCurrentAccelerator(alt_press); - EXPECT_EQ(alt_press, history.current_accelerator()); - EXPECT_NE(alt_press, history.previous_accelerator()); - - Accelerator search_alt_press(ui::VKEY_LWIN, ui::EF_ALT_DOWN, - ui::Accelerator::KeyState::PRESSED); - history.StoreCurrentAccelerator(search_alt_press); - EXPECT_EQ(search_alt_press, history.current_accelerator()); - EXPECT_EQ(alt_press, history.previous_accelerator()); - history.StoreCurrentAccelerator(search_alt_press); - EXPECT_EQ(search_alt_press, history.current_accelerator()); - EXPECT_EQ(alt_press, history.previous_accelerator()); - - Accelerator alt_release_search_down(ui::VKEY_MENU, ui::EF_COMMAND_DOWN, - ui::Accelerator::KeyState::RELEASED); - history.StoreCurrentAccelerator(alt_release_search_down); - EXPECT_EQ(alt_release_search_down, history.current_accelerator()); - EXPECT_EQ(search_alt_press, history.previous_accelerator()); - - // Search is still down and search presses will keep being generated, but from - // the perspective of the AcceleratorHistory, this is the same Search press - // that hasn't been released yet. - Accelerator search_press(ui::VKEY_LWIN, ui::EF_NONE, - ui::Accelerator::KeyState::PRESSED); - history.StoreCurrentAccelerator(search_press); - history.StoreCurrentAccelerator(search_press); - history.StoreCurrentAccelerator(search_press); - EXPECT_EQ(alt_release_search_down, history.current_accelerator()); - EXPECT_EQ(search_alt_press, history.previous_accelerator()); - - Accelerator search_release(ui::VKEY_LWIN, ui::EF_NONE, - ui::Accelerator::KeyState::RELEASED); - history.StoreCurrentAccelerator(search_release); - EXPECT_EQ(search_release, history.current_accelerator()); - EXPECT_EQ(alt_release_search_down, history.previous_accelerator()); -} - -// Tests that the record of pressed keys is cleared when language changes -// between key press and release. Detected via a release event that arrives with -// no corresponding press. See https://crbug.com/1184474. -TEST(AcceleratorHistoryTest, ReleaseWithNoMatchingPressClearsPressedKeys) { - // Press "]" aka ui::VKEY_OEM_6 in the US keyboard. - AcceleratorHistory history; - ui::Accelerator right_bracket_press(ui::VKEY_OEM_6, ui::EF_NONE, - ui::Accelerator::KeyState::PRESSED); - history.StoreCurrentAccelerator(right_bracket_press); - - // Simulate that a keyboard language change turns the release of "]" to - // VKEY_OEM_PLUS in a DE keyboard. So there should be a release event with no - // matching press. Test that the set of pressed keys is empty. - ui::Accelerator right_bracket_release(ui::VKEY_OEM_PLUS, ui::EF_NONE, - ui::Accelerator::KeyState::RELEASED); - history.StoreCurrentAccelerator(right_bracket_release); - EXPECT_TRUE(history.currently_pressed_keys().empty()); -} - -} // namespace ui diff --git a/chromium/ui/base/accelerators/accelerator_manager.cc b/chromium/ui/base/accelerators/accelerator_manager.cc index aed89311295..695f378c067 100644 --- a/chromium/ui/base/accelerators/accelerator_manager.cc +++ b/chromium/ui/base/accelerators/accelerator_manager.cc @@ -4,11 +4,8 @@ #include "ui/base/accelerators/accelerator_manager.h" -#include - #include "base/check.h" #include "base/containers/contains.h" -#include "base/notreached.h" namespace ui { @@ -23,58 +20,50 @@ void AcceleratorManager::Register( DCHECK(target); for (const ui::Accelerator& accelerator : accelerators) { - AcceleratorTargetList& targets = accelerators_[accelerator].second; - DCHECK(!base::Contains(targets, target)) - << "Registering the same target multiple times"; - - // All priority accelerators go to the front of the line. - if (priority == kHighPriority) { - DCHECK(!accelerators_[accelerator].first) - << "Only one high-priority handler can be registered"; - targets.push_front(target); - // Mark that we have a priority accelerator at the front. - accelerators_[accelerator].first = true; - } else { - // We are registering a normal priority handler. If no priority - // accelerator handler has been registered before us, just add the new - // handler to the front. Otherwise, register it after the first (only) - // priority handler. - if (!accelerators_[accelerator].first) - targets.push_front(target); - else - targets.insert(++targets.begin(), target); - } + accelerators_[accelerator].RegisterWithPriority(target, priority); } } void AcceleratorManager::Unregister(const Accelerator& accelerator, AcceleratorTarget* target) { + DCHECK(target); auto map_iter = accelerators_.find(accelerator); - if (map_iter == accelerators_.end()) { - NOTREACHED() << "Unregistering non-existing accelerator"; - return; - } + DCHECK(map_iter != accelerators_.end()) + << "Unregistering non-existing accelerator"; - UnregisterImpl(map_iter, target); + AcceleratorTargetInfo& target_info = map_iter->second; + 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); } void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) { for (auto map_iter = accelerators_.begin(); map_iter != accelerators_.end();) { - AcceleratorTargetList* targets = &map_iter->second.second; - if (!base::Contains(*targets, target)) { - ++map_iter; - } else { - auto tmp_iter = map_iter; - ++map_iter; - UnregisterImpl(tmp_iter, target); + AcceleratorTargetInfo& target_info = map_iter->second; + + // 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); + continue; } + + DCHECK(target_info.HasTargets()); + ++map_iter; } } bool AcceleratorManager::IsRegistered(const Accelerator& accelerator) const { auto map_iter = accelerators_.find(accelerator); - return map_iter != accelerators_.end() && !map_iter->second.second.empty(); + + // 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(); } bool AcceleratorManager::Process(const Accelerator& accelerator) { @@ -82,53 +71,103 @@ bool AcceleratorManager::Process(const Accelerator& accelerator) { if (map_iter == accelerators_.end()) return false; - // We have to copy the target list here, because an AcceleratorPressed - // event handler may modify the list. - AcceleratorTargetList targets(map_iter->second.second); - for (auto iter = targets.begin(); iter != targets.end(); ++iter) { - if ((*iter)->CanHandleAccelerators() && - (*iter)->AcceleratorPressed(accelerator)) { - return true; - } - } + // If the accelerator is in the map, the target list should not be empty. + AcceleratorTargetInfo& target_info = map_iter->second; + DCHECK(target_info.HasTargets()); - return false; + // We have to copy the target list here, because processing the accelerator + // event handler may modify the list. + 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() || map_iter->second.second.empty()) + if (map_iter == accelerators_.end()) return false; - // Check if we have a priority handler. If not, there's no more work needed. - if (!map_iter->second.first) - return false; + return map_iter->second.HasPriorityHandler(); +} - // If the priority handler says it cannot handle the accelerator, we must not - // count it as one. - return map_iter->second.second.front()->CanHandleAccelerators(); +AcceleratorManager::AcceleratorTargetInfo::AcceleratorTargetInfo() = default; + +AcceleratorManager::AcceleratorTargetInfo::AcceleratorTargetInfo( + const AcceleratorManager::AcceleratorTargetInfo& other) = default; + +AcceleratorManager::AcceleratorTargetInfo& +AcceleratorManager::AcceleratorTargetInfo::operator=( + const AcceleratorManager::AcceleratorTargetInfo& other) = default; + +AcceleratorManager::AcceleratorTargetInfo::~AcceleratorTargetInfo() = default; + +void AcceleratorManager::AcceleratorTargetInfo::RegisterWithPriority( + AcceleratorTarget* target, + HandlerPriority priority) { + DCHECK(!Contains(target)) << "Registering the same target multiple times"; + + // All priority accelerators go to the front of the line. + if (priority == kHighPriority) { + DCHECK(!has_priority_handler_) + << "Only one high-priority handler can be registered"; + targets_.push_front(target); + // Mark that we have a priority accelerator at the front. + has_priority_handler_ = true; + } else { + // We are registering a normal priority handler. If no priority + // accelerator handler has been registered before us, just add the new + // handler to the front. Otherwise, register it after the first (only) + // priority handler. + if (has_priority_handler_) { + DCHECK(!targets_.empty()); + targets_.insert(++targets_.begin(), target); + } else { + targets_.push_front(target); + } + } + + // Post condition. Ensure there's at least one target. + DCHECK(!targets_.empty()); } -void AcceleratorManager::UnregisterImpl( - AcceleratorTargetsMap::iterator map_iter, +bool AcceleratorManager::AcceleratorTargetInfo::Unregister( AcceleratorTarget* target) { - AcceleratorTargetList* targets = &map_iter->second.second; - auto target_iter = std::find(targets->begin(), targets->end(), target); - if (target_iter == targets->end()) { - NOTREACHED() << "Unregistering accelerator for wrong target"; - return; - } + DCHECK(!targets_.empty()); // Only one priority handler is allowed, so if we remove the first element we // no longer have a priority target. - if (target_iter == targets->begin()) - map_iter->second.first = false; + if (targets_.front() == target) + has_priority_handler_ = false; + + // Attempt to remove the target and return true if it was present. + const size_t original_target_count = targets_.size(); + targets_.remove(target); + return original_target_count != targets_.size(); +} + +bool AcceleratorManager::AcceleratorTargetInfo::TryProcess( + const Accelerator& accelerator) { + DCHECK(!targets_.empty()); + + for (AcceleratorTarget* target : targets_) { + if (target->CanHandleAccelerators() && + target->AcceleratorPressed(accelerator)) { + return true; + } + } - targets->remove(target); - if (!targets->empty()) - return; - accelerators_.erase(map_iter); + return false; +} + +bool AcceleratorManager::AcceleratorTargetInfo::HasPriorityHandler() const { + DCHECK(!targets_.empty()); + return has_priority_handler_ && targets_.front()->CanHandleAccelerators(); +} + +bool AcceleratorManager::AcceleratorTargetInfo::Contains( + AcceleratorTarget* target) const { + DCHECK(target); + return base::Contains(targets_, target); } } // namespace ui diff --git a/chromium/ui/base/accelerators/accelerator_manager.h b/chromium/ui/base/accelerators/accelerator_manager.h index 3a0fb79f1db..0586b8cd204 100644 --- a/chromium/ui/base/accelerators/accelerator_manager.h +++ b/chromium/ui/base/accelerators/accelerator_manager.h @@ -7,13 +7,10 @@ #include #include -#include #include #include "base/component_export.h" -#include "base/macros.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/events/event_constants.h" namespace ui { @@ -27,6 +24,8 @@ class COMPONENT_EXPORT(UI_BASE) AcceleratorManager { }; AcceleratorManager(); + AcceleratorManager(const AcceleratorManager& other) = delete; + AcceleratorManager& operator=(const AcceleratorManager& other) = delete; ~AcceleratorManager(); // Register keyboard accelerators for the specified target. If multiple @@ -59,9 +58,11 @@ class COMPONENT_EXPORT(UI_BASE) AcceleratorManager { } // Unregister the specified keyboard accelerator for the specified target. + // DCHECKs if |target| is null or not registered. void Unregister(const Accelerator& accelerator, AcceleratorTarget* target); - // Unregister all keyboard accelerator for the specified target. + // Unregister all keyboard accelerator for the specified target. DCHECKs if + // |target| is null. void UnregisterAll(AcceleratorTarget* target); // Returns whether |accelerator| is already registered. @@ -79,21 +80,45 @@ class COMPONENT_EXPORT(UI_BASE) AcceleratorManager { bool HasPriorityHandler(const Accelerator& accelerator) const; private: - // The accelerators and associated targets. - using AcceleratorTargetList = std::list; - // This construct pairs together a |bool| (denoting whether the list contains - // a priority_handler at the front) with the list of AcceleratorTargets. - using AcceleratorTargets = std::pair; - using AcceleratorTargetsMap = std::map; - - // Implementation of Unregister(). |map_iter| points to the accelerator to - // remove, and |target| the AcceleratorTarget to remove. - void UnregisterImpl(AcceleratorTargetsMap::iterator map_iter, - AcceleratorTarget* target); - - AcceleratorTargetsMap accelerators_; + // 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 + // handlers. If present this handler is tried first, otherwise all handlers + // are tried in registration order. + class AcceleratorTargetInfo { + public: + AcceleratorTargetInfo(); + AcceleratorTargetInfo(const AcceleratorTargetInfo& other); + AcceleratorTargetInfo& operator=(const AcceleratorTargetInfo& other); + ~AcceleratorTargetInfo(); + + // Registers a |target| with a given |priority|. + void RegisterWithPriority(AcceleratorTarget* target, + HandlerPriority priority); + + // Unregisters |target| if it exists. Returns true if |target| was present. + bool Unregister(AcceleratorTarget* target); + + // Iterate through the targets in priority order attempting to process + // |accelerator|. Returns true if a target processed |accelerator|. + bool TryProcess(const Accelerator& accelerator); + + // Returns true if this set of targets has a priority handler and it can + // currently handle an accelerator. + bool HasPriorityHandler() const; + + // Returns true if |target| is registered. Note this is O(num_targets). + bool Contains(AcceleratorTarget* target) const; + + // Returns true if there are registered targets. + bool HasTargets() const { return !targets_.empty(); } + + private: + std::list targets_; + bool has_priority_handler_ = false; + }; - DISALLOW_COPY_AND_ASSIGN(AcceleratorManager); + // The accelerators and associated targets. + std::map accelerators_; }; } // namespace ui diff --git a/chromium/ui/base/accelerators/accelerator_unittest.cc b/chromium/ui/base/accelerators/accelerator_unittest.cc index 5a760ea6224..74282004e8e 100644 --- a/chromium/ui/base/accelerators/accelerator_unittest.cc +++ b/chromium/ui/base/accelerators/accelerator_unittest.cc @@ -4,7 +4,8 @@ #include "ui/base/accelerators/accelerator.h" -#include "base/strings/string16.h" +#include + #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -45,32 +46,32 @@ TEST(AcceleratorTest, MAYBE_GetShortcutText) { struct { KeyboardCode code; int modifiers; - const char* expected_long; - const char* expected_short; + const char16_t* expected_long; + const char16_t* expected_short; } keys[] = { - {VKEY_Q, EF_CONTROL_DOWN | EF_SHIFT_DOWN, "Ctrl+Shift+Q", "\u2303\u21e7Q"}, - {VKEY_A, EF_ALT_DOWN | EF_SHIFT_DOWN, "Alt+Shift+A", "\u2325\u21e7A"}, + {VKEY_Q, EF_CONTROL_DOWN | EF_SHIFT_DOWN, u"Ctrl+Shift+Q", u"⌃⇧Q"}, + {VKEY_A, EF_ALT_DOWN | EF_SHIFT_DOWN, u"Alt+Shift+A", u"⌥⇧A"}, // Regression test for https://crbug.com/867732: - {VKEY_OEM_COMMA, EF_CONTROL_DOWN, "Ctrl+Comma", "\u2303,"}, -#if defined(OS_APPLE) - {VKEY_T, EF_COMMAND_DOWN | EF_CONTROL_DOWN, nullptr, "\u2303\u2318T"}, + {VKEY_OEM_COMMA, EF_CONTROL_DOWN, u"Ctrl+Comma", u"⌃,"}, +#if defined(OS_MAC) + {VKEY_T, EF_COMMAND_DOWN | EF_CONTROL_DOWN, nullptr, u"⌃⌘T"}, #endif }; for (const auto& key : keys) { - base::string16 text = + std::u16string text = Accelerator(key.code, key.modifiers).GetShortcutText(); -#if defined(OS_APPLE) - EXPECT_EQ(text, base::UTF8ToUTF16(key.expected_short)); +#if defined(OS_MAC) + EXPECT_EQ(text, key.expected_short); #else - EXPECT_EQ(text, base::UTF8ToUTF16(key.expected_long)); + EXPECT_EQ(text, key.expected_long); #endif } } TEST(AcceleratorTest, ShortcutTextForUnknownKey) { const Accelerator accelerator(VKEY_UNKNOWN, EF_NONE); - EXPECT_EQ(base::string16(), accelerator.GetShortcutText()); + EXPECT_EQ(std::u16string(), accelerator.GetShortcutText()); } } // namespace ui diff --git a/chromium/ui/base/accelerators/menu_label_accelerator_util.cc b/chromium/ui/base/accelerators/menu_label_accelerator_util.cc index 4be00ab2309..d6da4b89f6c 100644 --- a/chromium/ui/base/accelerators/menu_label_accelerator_util.cc +++ b/chromium/ui/base/accelerators/menu_label_accelerator_util.cc @@ -9,14 +9,14 @@ namespace ui { -base::char16 GetMnemonic(const base::string16& label) { +char16_t GetMnemonic(const std::u16string& label) { size_t index = 0; do { index = label.find('&', index); - if (index != base::string16::npos) { + if (index != std::u16string::npos) { if (index + 1 != label.size()) { if (label[index + 1] != '&') { - base::char16 char_array[] = {label[index + 1], 0}; + char16_t char_array[] = {label[index + 1], 0}; // TODO(jshin): What about Turkish locale? See http://crbug.com/81719. // If the mnemonic is capital I and the UI language is Turkish, // lowercasing it results in 'small dotless i', which is different @@ -28,14 +28,14 @@ base::char16 GetMnemonic(const base::string16& label) { } index++; } - } while (index != base::string16::npos); + } while (index != std::u16string::npos); return 0; } -base::string16 EscapeMenuLabelAmpersands(const base::string16& label) { - base::string16 ret; - static const base::char16 kAmps[] = {'&', 0}; - static const base::char16 kTwoAmps[] = {'&', '&', 0}; +std::u16string EscapeMenuLabelAmpersands(const std::u16string& label) { + std::u16string ret; + static const char16_t kAmps[] = {'&', 0}; + static const char16_t kTwoAmps[] = {'&', '&', 0}; base::ReplaceChars(label, kAmps, kTwoAmps, &ret); return ret; } diff --git a/chromium/ui/base/accelerators/menu_label_accelerator_util.h b/chromium/ui/base/accelerators/menu_label_accelerator_util.h index fcdcd206a09..87f49302dad 100644 --- a/chromium/ui/base/accelerators/menu_label_accelerator_util.h +++ b/chromium/ui/base/accelerators/menu_label_accelerator_util.h @@ -8,16 +8,15 @@ #include #include "base/component_export.h" -#include "base/strings/string16.h" namespace ui { -COMPONENT_EXPORT(UI_BASE) base::char16 GetMnemonic(const base::string16& label); +COMPONENT_EXPORT(UI_BASE) char16_t GetMnemonic(const std::u16string& label); // This function escapes every '&' in label by replacing it with '&&', to avoid // having single ampersands in user-provided strings treated as accelerators. COMPONENT_EXPORT(UI_BASE) -base::string16 EscapeMenuLabelAmpersands(const base::string16& label); +std::u16string EscapeMenuLabelAmpersands(const std::u16string& label); } // namespace ui diff --git a/chromium/ui/base/accelerators/menu_label_accelerator_util_unittest.cc b/chromium/ui/base/accelerators/menu_label_accelerator_util_unittest.cc index 8d4b64d8ec2..f518472d7af 100644 --- a/chromium/ui/base/accelerators/menu_label_accelerator_util_unittest.cc +++ b/chromium/ui/base/accelerators/menu_label_accelerator_util_unittest.cc @@ -11,12 +11,11 @@ namespace ui { TEST(MenuLabelAcceleratorTest, GetMnemonic) { static const struct { - const base::string16 label; - const base::char16 mneumonic; + const std::u16string label; + const char16_t mneumonic; } cases[] = { - {base::ASCIIToUTF16(""), 0}, {base::ASCIIToUTF16("Exit"), 0}, - {base::ASCIIToUTF16("E&xit"), 'x'}, {base::ASCIIToUTF16("E&&xit"), 0}, - {base::ASCIIToUTF16("E&xi&t"), 'x'}, {base::ASCIIToUTF16("Exit&"), 0}, + {u"", 0}, {u"Exit", 0}, {u"E&xit", 'x'}, + {u"E&&xit", 0}, {u"E&xi&t", 'x'}, {u"Exit&", 0}, }; for (const auto& test : cases) EXPECT_EQ(GetMnemonic(test.label), test.mneumonic); @@ -42,8 +41,8 @@ TEST(MenuLabelAcceleratorTest, EscapeMenuLabelAmpersands) { }; for (const auto& test : cases) { - base::string16 in = base::ASCIIToUTF16(test.input); - base::string16 out = base::ASCIIToUTF16(test.output); + std::u16string in = base::ASCIIToUTF16(test.input); + std::u16string out = base::ASCIIToUTF16(test.output); EXPECT_EQ(out, EscapeMenuLabelAmpersands(in)); } } diff --git a/chromium/ui/base/clipboard/BUILD.gn b/chromium/ui/base/clipboard/BUILD.gn index 6e806368add..e710361b70b 100644 --- a/chromium/ui/base/clipboard/BUILD.gn +++ b/chromium/ui/base/clipboard/BUILD.gn @@ -4,7 +4,6 @@ import("///build/config/ozone.gni") import("//build/config/chromeos/ui_mode.gni") -import("//build/config/chromeos/ui_mode.gni") import("//build/config/ui.gni") component("clipboard_types") { @@ -130,33 +129,7 @@ component("clipboard") { ] if (use_aura) { - # Linux clipboard implementations. - if ((is_linux || is_chromeos_lacros) && !is_chromecast) { - sources += [ "clipboard_linux.cc" ] - if (use_ozone) { - sources += [ - "clipboard_ozone.cc", - "clipboard_ozone.h", - ] - deps += [ "//ui/base" ] - } - if (use_x11) { - sources += [ - "clipboard_x11.cc", - "clipboard_x11.h", - ] - deps += [ - "//ui/base", - "//ui/base/x", - "//ui/events/platform", - "//ui/events/platform/x11", - "//ui/events/x", - "//ui/gfx/x", - ] - } - } else if (is_chromeos_ash && ozone_platform_x11) { - # linux-chromeos uses non-backed clipboard by default, but supports ozone - # x11 with flag --use-system-clipbboard. + if (use_ozone) { sources += [ "clipboard_data.cc", "clipboard_data.h", @@ -165,16 +138,29 @@ component("clipboard") { "clipboard_ozone.cc", "clipboard_ozone.h", ] - deps += [ "//ui/base" ] - } else if (!is_win) { - # This file is used for all builds not backed by an underlying platform. + deps += [ "//ui/ozone" ] + } + + if (use_x11) { sources += [ - "clipboard_data.cc", - "clipboard_data.h", - "clipboard_non_backed.cc", - "clipboard_non_backed.h", + "clipboard_x11.cc", + "clipboard_x11.h", + ] + deps += [ + "//ui/base", + "//ui/base/x", + "//ui/events/platform", + "//ui/events/platform/x11", + "//ui/events/x", + "//ui/gfx/x", ] } + + # TODO(crbug.com/1096425): Cleanup when non-Ozone path gets dropped. + if (use_ozone || use_x11) { + sources += [ "clipboard_factory_ozone.cc" ] + deps += [ "//ui/base" ] + } } if (is_android) { @@ -188,10 +174,6 @@ component("clipboard") { "CoreFoundation.framework", ] } - - if (use_ozone) { - deps += [ "//ui/ozone" ] - } } source_set("clipboard_test_support") { @@ -216,7 +198,12 @@ source_set("clipboard_test_support") { "//skia", ] - deps = [ "//base/test:test_support" ] + deps = [ + "//base/test:test_support", + "//build:chromecast_buildflags", + "//build:chromeos_buildflags", + "//ui/base:features", + ] if (is_android) { deps += [ "//ui/android:ui_javatest_jni_headers" ] diff --git a/chromium/ui/base/clipboard/OWNERS b/chromium/ui/base/clipboard/OWNERS index e48dbe775ee..3520663eec7 100644 --- a/chromium/ui/base/clipboard/OWNERS +++ b/chromium/ui/base/clipboard/OWNERS @@ -1,6 +1,7 @@ dcheng@chromium.org huangdarwin@chromium.org -per-file clipboard_ozone*=msisov@igalia.com -per-file clipboard_ozone*=adunaev@igalia.com +per-file clipboard_*ozone*=msisov@igalia.com +per-file clipboard_*ozone*=adunaev@igalia.com +per-file clipboard_*x11*=thomasanderson@chromium.org diff --git a/chromium/ui/base/clipboard/clipboard.cc b/chromium/ui/base/clipboard/clipboard.cc index 3735eff0e7a..83fd6aa2e71 100644 --- a/chromium/ui/base/clipboard/clipboard.cc +++ b/chromium/ui/base/clipboard/clipboard.cc @@ -15,6 +15,7 @@ #include "build/chromeos_buildflags.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" +#include "url/gurl.h" #if defined(USE_OZONE) #include "ui/base/ui_base_features.h" @@ -149,8 +150,8 @@ void Clipboard::DispatchPortableRepresentation(PortableFormat format, if (params.size() == 2) { if (params[1].empty()) return; - WriteHTML(&(params[0].front()), params[0].size(), - &(params[1].front()), params[1].size()); + WriteHTML(&(params[0].front()), params[0].size(), &(params[1].front()), + params[1].size()); } else if (params.size() == 1) { WriteHTML(&(params[0].front()), params[0].size(), nullptr, 0); } @@ -248,4 +249,97 @@ bool Clipboard::IsMarkedByOriginatorAsConfidential() const { void Clipboard::MarkAsConfidential() {} +void Clipboard::ReadAvailableTypes(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadAvailableTypesCallback callback) const { + std::vector types; + ReadAvailableTypes(buffer, data_dst, &types); + std::move(callback).Run(std::move(types)); +} + +void Clipboard::ReadAvailablePlatformSpecificFormatNames( + ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadAvailablePlatformSpecificFormatNamesCallback callback) const { + std::move(callback).Run( + ReadAvailablePlatformSpecificFormatNames(buffer, data_dst)); +} + +void Clipboard::ReadText(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadTextCallback callback) const { + std::u16string result; + ReadText(buffer, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + +void Clipboard::ReadAsciiText(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadAsciiTextCallback callback) const { + std::string result; + ReadAsciiText(buffer, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + +void Clipboard::ReadHTML(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadHtmlCallback callback) const { + std::u16string markup; + std::string src_url; + uint32_t fragment_start; + uint32_t fragment_end; + ReadHTML(buffer, data_dst, &markup, &src_url, &fragment_start, &fragment_end); + std::move(callback).Run(std::move(markup), GURL(src_url), fragment_start, + fragment_end); +} + +void Clipboard::ReadSvg(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadSvgCallback callback) const { + std::u16string result; + ReadSvg(buffer, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + +void Clipboard::ReadRTF(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadRTFCallback callback) const { + std::string result; + ReadRTF(buffer, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + +void Clipboard::ReadCustomData(ClipboardBuffer buffer, + const std::u16string& type, + const DataTransferEndpoint* data_dst, + ReadCustomDataCallback callback) const { + std::u16string result; + ReadCustomData(buffer, type, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + +void Clipboard::ReadFilenames(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + ReadFilenamesCallback callback) const { + std::vector result; + ReadFilenames(buffer, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + +void Clipboard::ReadBookmark(const DataTransferEndpoint* data_dst, + ReadBookmarkCallback callback) const { + std::u16string title; + std::string url; + ReadBookmark(data_dst, &title, &url); + std::move(callback).Run(std::move(title), GURL(url)); +} + +void Clipboard::ReadData(const ClipboardFormatType& format, + const DataTransferEndpoint* data_dst, + ReadDataCallback callback) const { + std::string result; + ReadData(format, data_dst, &result); + std::move(callback).Run(std::move(result)); +} + } // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard.h b/chromium/ui/base/clipboard/clipboard.h index bcd96bf03f3..82d35fe8f88 100644 --- a/chromium/ui/base/clipboard/clipboard.h +++ b/chromium/ui/base/clipboard/clipboard.h @@ -19,7 +19,6 @@ #include "base/macros.h" #include "base/no_destructor.h" #include "base/process/process.h" -#include "base/strings/string16.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" #include "base/threading/thread_checker.h" @@ -31,6 +30,7 @@ #include "ui/base/clipboard/file_info.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" +class GURL; class SkBitmap; namespace ui { @@ -43,12 +43,30 @@ class DataTransferEndpoint; // - specifies an ordering in which to write types to the clipboard // (see PortableFormat). // - is generalized for all targets/operating systems. -// TODO(https://crbug.com/443355): Make all functions asynchronous. -// Currently, only ReadImage() is asynchronous, but eventually, we would like -// all interfaces to be async. class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard : public base::ThreadChecker { public: + using ReadAvailableTypesCallback = + base::OnceCallback result)>; + using ReadAvailablePlatformSpecificFormatNamesCallback = + base::OnceCallback result)>; + using ReadTextCallback = base::OnceCallback; + using ReadAsciiTextCallback = base::OnceCallback; + using ReadHtmlCallback = base::OnceCallback; + using ReadSvgCallback = base::OnceCallback; + using ReadRTFCallback = base::OnceCallback; + using ReadImageCallback = base::OnceCallback; + using ReadCustomDataCallback = + base::OnceCallback; + using ReadFilenamesCallback = + base::OnceCallback result)>; + using ReadBookmarkCallback = + base::OnceCallback; + using ReadDataCallback = base::OnceCallback; + static bool IsSupportedClipboardBuffer(ClipboardBuffer buffer); // Sets the list of threads that are allowed to access the clipboard. @@ -119,29 +137,29 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard // Clear the clipboard data. virtual void Clear(ClipboardBuffer buffer) = 0; - // TODO(huangdarwin): Refactor ReadAvailableTypes to return |types|. // TODO(huangdarwin): Rename to ReadAvailablePortableFormatNames(). // Includes all sanitized types. // Also, includes pickled types by splitting them out of the pickled format. virtual void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const = 0; + ReadAvailableTypesCallback callback) const; // Includes all types, including unsanitized types. // Omits formats held within pickles, as they're different from what a native // application would see. - virtual std::vector ReadAvailablePlatformSpecificFormatNames( + virtual void ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, - const DataTransferEndpoint* data_dst) const = 0; + const DataTransferEndpoint* data_dst, + ReadAvailablePlatformSpecificFormatNamesCallback callback) const; // Reads Unicode text from the clipboard, if available. virtual void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const = 0; + ReadTextCallback callback) const; // Reads ASCII text from the clipboard, if available. virtual void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::string* result) const = 0; + ReadAsciiTextCallback callback) const; // Reads HTML from the clipboard, if available. If the HTML fragment requires // context to parse, |fragment_start| and |fragment_end| are indexes into @@ -149,22 +167,18 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard // they will contain 0 and markup->size(). virtual void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, - std::string* src_url, - uint32_t* fragment_start, - uint32_t* fragment_end) const = 0; + ReadHtmlCallback callback) const; // Reads an SVG image from the clipboard, if available. virtual void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const = 0; + ReadSvgCallback callback) const; + // Reads RTF from the clipboard, if available. Stores the result as a byte // vector. virtual void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::string* result) const = 0; - - using ReadImageCallback = base::OnceCallback; + ReadRTFCallback callback) const; // Reads an image from the clipboard, if available. virtual void ReadImage(ClipboardBuffer buffer, @@ -172,23 +186,62 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard ReadImageCallback callback) const = 0; virtual void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const = 0; + ReadCustomDataCallback callback) const; // Reads filenames from the clipboard, if available. virtual void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* result) const = 0; + ReadFilenamesCallback callback) const; // Reads a bookmark from the clipboard, if available. // |title| or |url| may be null. virtual void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, - std::string* url) const = 0; + ReadBookmarkCallback callback) const; // Reads raw data from the clipboard with the given format type. Stores result // as a byte vector. + virtual void ReadData(const ClipboardFormatType& format, + const DataTransferEndpoint* data_dst, + ReadDataCallback callback) const; + + // Synchronous reads are deprecated (https://crbug.com/443355). Please use the + // equivalent functions that take callbacks above. + virtual void ReadAvailableTypes(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::vector* types) const = 0; + virtual std::vector ReadAvailablePlatformSpecificFormatNames( + ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst) const = 0; + virtual void ReadText(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::u16string* result) const = 0; + virtual void ReadAsciiText(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::string* result) const = 0; + virtual void ReadHTML(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::u16string* markup, + std::string* src_url, + uint32_t* fragment_start, + uint32_t* fragment_end) const = 0; + virtual void ReadSvg(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::u16string* result) const = 0; + virtual void ReadRTF(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::string* result) const = 0; + virtual void ReadCustomData(ClipboardBuffer buffer, + const std::u16string& type, + const DataTransferEndpoint* data_dst, + std::u16string* result) const = 0; + virtual void ReadFilenames(ClipboardBuffer buffer, + const DataTransferEndpoint* data_dst, + std::vector* result) const = 0; + virtual void ReadBookmark(const DataTransferEndpoint* data_dst, + std::u16string* title, + std::string* url) const = 0; virtual void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, std::string* result) const = 0; diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc index 7ad02c4c37f..dd32059ebab 100644 --- a/chromium/ui/base/clipboard/clipboard_android.cc +++ b/chromium/ui/base/clipboard/clipboard_android.cc @@ -115,7 +115,11 @@ class ClipboardMap { // Updates |last_modified_time_| to |time| and writes it to |local_state_|. void UpdateLastModifiedTime(base::Time time); - // Updates |map_| and |map_state_| if necessary by fetching data from Java. + // Updates 'map_' and 'map_state_' if necessary by fetching data from Java. + // Start from Android S, accessing the system clipboard will cause a + // pop up notification showing that the app copied content from clipboard. To + // avoid that, This function should only be called when we really need to read + // the data. void UpdateFromAndroidClipboard(); std::map map_ GUARDED_BY(lock_); @@ -176,17 +180,68 @@ void ClipboardMap::ClearLastModifiedTime() { bool ClipboardMap::HasFormat(const ClipboardFormatType& format) { base::AutoLock lock(lock_); - UpdateFromAndroidClipboard(); + if (map_state_ == MapState::kUpToDate) { + // If the 'map_' is up to date, we can just check with it. + return base::Contains(map_, format); + } + + // If the 'map_' is not up to date, we need to check with the system if the + // formats are supported by Android clipboard. + // We will not update the map from here since update the map will update both + // formats and data, but we only need format info here. Also, reading data + // from the system clipboard will cause clipboard access notification popping + // up. + JNIEnv* env = AttachCurrentThread(); + // TODO(crbug.com/1194601): Create a single method for the follow JNI calls. + if (format == ClipboardFormatType::GetPlainTextType()) { + return Java_Clipboard_hasCoercedText(env, clipboard_manager_); + } else if (format == ClipboardFormatType::GetHtmlType()) { + return Java_Clipboard_hasHTMLOrStyledText(env, clipboard_manager_); + } else if (format == ClipboardFormatType::GetUrlType()) { + return Java_Clipboard_hasUrl(env, clipboard_manager_); + } else if (format == ClipboardFormatType::GetType(kMimeTypeImageURI)) { + return Java_Clipboard_hasImage(env, clipboard_manager_); + } + + // Android unsupported format types, check local only. return base::Contains(map_, format); } std::vector ClipboardMap::GetFormats() { base::AutoLock lock(lock_); - UpdateFromAndroidClipboard(); std::vector formats; formats.reserve(map_.size()); - for (const auto& it : map_) + + // Check with Android for Android clipboard supported formats. + if (map_state_ != MapState::kUpToDate) { + JNIEnv* env = AttachCurrentThread(); + if (Java_Clipboard_hasCoercedText(env, clipboard_manager_)) { + formats.push_back(ClipboardFormatType::GetPlainTextType()); + } + if (Java_Clipboard_hasHTMLOrStyledText(env, clipboard_manager_)) { + formats.push_back(ClipboardFormatType::GetHtmlType()); + } + if (Java_Clipboard_hasUrl(env, clipboard_manager_)) { + formats.push_back(ClipboardFormatType::GetUrlType()); + } + if (Java_Clipboard_hasImage(env, clipboard_manager_)) { + formats.push_back(ClipboardFormatType::GetBitmapType()); + } + } + + // Check local cache, since the formats not supported by Android clipboard are + // not synced on any other layer. + for (const auto& it : map_) { + if (map_state_ != MapState::kUpToDate && + (it.first == ClipboardFormatType::GetPlainTextType() || + it.first == ClipboardFormatType::GetHtmlType() || + it.first == ClipboardFormatType::GetUrlType() || + it.first == ClipboardFormatType::GetType(kMimeTypeImageURI))) { + continue; + } formats.push_back(it.first); + } + return formats; } @@ -304,6 +359,8 @@ void ClipboardMap::UpdateFromAndroidClipboard() { Java_Clipboard_getCoercedText(env, clipboard_manager_); ScopedJavaLocalRef jhtml = Java_Clipboard_getHTMLText(env, clipboard_manager_); + ScopedJavaLocalRef jurl = + Java_Clipboard_getUrl(env, clipboard_manager_); ScopedJavaLocalRef jimageuri = Java_Clipboard_getImageUriString(env, clipboard_manager_); @@ -311,6 +368,8 @@ void ClipboardMap::UpdateFromAndroidClipboard() { jtext); JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::GetHtmlType(), jhtml); + JNI_Clipboard_AddMapEntry(env, &map_, ClipboardFormatType::GetUrlType(), + jurl); JNI_Clipboard_AddMapEntry( env, &map_, ClipboardFormatType::GetType(kMimeTypeImageURI), jimageuri); @@ -405,7 +464,7 @@ void ClipboardAndroid::Clear(ClipboardBuffer buffer) { void ClipboardAndroid::ReadAvailableTypes( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const { + std::vector* types) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); DCHECK(types); @@ -430,14 +489,14 @@ void ClipboardAndroid::ReadAvailableTypes( // |data_dst| is not used. It's only passed to be consistent with other // platforms. -std::vector +std::vector ClipboardAndroid::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); std::vector formats = g_map.Get().GetFormats(); - std::vector types; + std::vector types; types.reserve(formats.size()); for (const ClipboardFormatType& format : formats) types.push_back(base::UTF8ToUTF16(format.GetName())); @@ -449,7 +508,7 @@ ClipboardAndroid::ReadAvailablePlatformSpecificFormatNames( // platforms. void ClipboardAndroid::ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); std::string utf8; @@ -473,7 +532,7 @@ void ClipboardAndroid::ReadAsciiText(ClipboardBuffer buffer, // platforms. void ClipboardAndroid::ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -494,7 +553,7 @@ void ClipboardAndroid::ReadHTML(ClipboardBuffer buffer, // platforms. void ClipboardAndroid::ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); std::string utf8 = g_map.Get().Get(ClipboardFormatType::GetSvgType()); @@ -524,9 +583,9 @@ void ClipboardAndroid::ReadImage(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardAndroid::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); NOTIMPLEMENTED(); } @@ -540,13 +599,14 @@ void ClipboardAndroid::ReadFilenames(ClipboardBuffer buffer, NOTIMPLEMENTED(); } -// |data_dst| is not used. It's only passed to be consistent with other -// platforms. +// 'data_dst' and 'title' are not used. It's only passed to be consistent with +// other platforms. void ClipboardAndroid::ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const { DCHECK(CalledOnValidThread()); - NOTIMPLEMENTED(); + RecordRead(ClipboardFormatMetric::kBookmark); + *url = g_map.Get().Get(ClipboardFormatType::GetUrlType()); } // |data_dst| is not used. It's only passed to be consistent with other diff --git a/chromium/ui/base/clipboard/clipboard_android.h b/chromium/ui/base/clipboard/clipboard_android.h index 6ad7e758d22..c8e23a49527 100644 --- a/chromium/ui/base/clipboard/clipboard_android.h +++ b/chromium/ui/base/clipboard/clipboard_android.h @@ -66,25 +66,25 @@ class ClipboardAndroid : public Clipboard { void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const override; - std::vector ReadAvailablePlatformSpecificFormatNames( + std::vector* types) const override; + std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const override; void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const override; void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; @@ -92,15 +92,14 @@ class ClipboardAndroid : public Clipboard { const DataTransferEndpoint* data_dst, ReadImageCallback callback) const override; void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* result) const override; void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, - + std::u16string* title, std::string* url) const override; void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, diff --git a/chromium/ui/base/clipboard/clipboard_android_test_support.cc b/chromium/ui/base/clipboard/clipboard_android_test_support.cc index 30b2d5ba81d..b7f126afcfb 100644 --- a/chromium/ui/base/clipboard/clipboard_android_test_support.cc +++ b/chromium/ui/base/clipboard/clipboard_android_test_support.cc @@ -25,7 +25,7 @@ jboolean JNI_ClipboardAndroidTestSupport_NativeWriteHtml( { // Simulate something writing HTML to the clipboard in native. // Android requires both a plaintext and HTML version. - base::string16 html_text; + std::u16string html_text; base::android::ConvertJavaStringToUTF16(env, j_html_text, &html_text); std::string url; ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); diff --git a/chromium/ui/base/clipboard/clipboard_factory_ozone.cc b/chromium/ui/base/clipboard/clipboard_factory_ozone.cc new file mode 100644 index 00000000000..e2a061df868 --- /dev/null +++ b/chromium/ui/base/clipboard/clipboard_factory_ozone.cc @@ -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. + +#include "ui/base/clipboard/clipboard.h" + +#include "base/command_line.h" +#include "base/notreached.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" +#include "ui/base/clipboard/clipboard_non_backed.h" +#include "ui/base/ui_base_features.h" +#include "ui/base/ui_base_switches.h" + +#if defined(USE_OZONE) +#include "ui/base/clipboard/clipboard_ozone.h" +#include "ui/ozone/public/ozone_platform.h" +#endif + +#if defined(USE_X11) +#include "ui/base/clipboard/clipboard_x11.h" +#endif + +namespace ui { + +// Clipboard factory method. +// TODO(crbug.com/1096425): Cleanup when non-Ozone path gets dropped. +Clipboard* Clipboard::Create() { + // On Linux Desktop builds ozone usage depends on UseOzonePlatform feature. + // For all the other Ozone builds, this is set to true. + bool use_ozone_impl = features::IsUsingOzonePlatform(); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Use platform-backed implementation iff --use-system-clipbboard is passed. + use_ozone_impl &= base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseSystemClipboard); +#endif + +#if defined(USE_X11) + // Use X11 implementation unless UseOzonePlatform feature is enabled. + if (!use_ozone_impl) + return new ClipboardX11; +#endif + +#if defined(USE_OZONE) + if (use_ozone_impl && OzonePlatform::GetInstance()->GetPlatformClipboard()) + return new ClipboardOzone; +#endif + +#if defined(USE_X11) && BUILDFLAG(IS_CHROMEOS_LACROS) + NOTREACHED() << "System clipboard integration should be in place."; +#endif + return new ClipboardNonBacked; +} + +} // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard_format_type.h b/chromium/ui/base/clipboard/clipboard_format_type.h index 982209eddf7..982ea528952 100644 --- a/chromium/ui/base/clipboard/clipboard_format_type.h +++ b/chromium/ui/base/clipboard/clipboard_format_type.h @@ -116,7 +116,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) ClipboardFormatType { // these format types can be used by drag and drop code as well. // // In all platforms, format names may be ASCII or UTF8/16. - // TODO(huangdarwin): Convert interfaces to base::string16. + // TODO(huangdarwin): Convert interfaces to std::u16string. #if defined(OS_WIN) // When there are multiple files in the data store and they are described // using a file group descriptor, the file contents are retrieved by diff --git a/chromium/ui/base/clipboard/clipboard_linux.cc b/chromium/ui/base/clipboard/clipboard_linux.cc deleted file mode 100644 index ef42052ed5d..00000000000 --- a/chromium/ui/base/clipboard/clipboard_linux.cc +++ /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. - -#include "ui/base/clipboard/clipboard.h" - -#if defined(USE_OZONE) -#include "ui/base/clipboard/clipboard_ozone.h" -#include "ui/base/ui_base_features.h" -#endif - -#if defined(USE_X11) -#include "ui/base/clipboard/clipboard_x11.h" -#endif - -namespace ui { - -// Clipboard factory method. -Clipboard* Clipboard::Create() { -#if defined(USE_OZONE) - if (features::IsUsingOzonePlatform()) - return new ClipboardOzone(); -#endif - -#if defined(USE_X11) - return new ClipboardX11(); -#else - NOTREACHED(); - return nullptr; -#endif -} - -} // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard_mac.h b/chromium/ui/base/clipboard/clipboard_mac.h index fbf4e3a6583..e517301e047 100644 --- a/chromium/ui/base/clipboard/clipboard_mac.h +++ b/chromium/ui/base/clipboard/clipboard_mac.h @@ -40,25 +40,25 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard { void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const override; - std::vector ReadAvailablePlatformSpecificFormatNames( + std::vector* types) const override; + std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const override; void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const override; void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; @@ -66,14 +66,14 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard { const DataTransferEndpoint* data_dst, ReadImageCallback callback) const override; void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* result) const override; void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const override; void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, diff --git a/chromium/ui/base/clipboard/clipboard_mac.mm b/chromium/ui/base/clipboard/clipboard_mac.mm index d5379d8fddb..5dedaf79e22 100644 --- a/chromium/ui/base/clipboard/clipboard_mac.mm +++ b/chromium/ui/base/clipboard/clipboard_mac.mm @@ -79,8 +79,7 @@ uint64_t ClipboardMac::GetSequenceNumber(ClipboardBuffer buffer) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); - NSPasteboard* pb = GetPasteboard(); - return [pb changeCount]; + return [GetPasteboard() changeCount]; } // |data_dst| is not used. It's only passed to be consistent with other @@ -98,8 +97,8 @@ bool ClipboardMac::IsFormatAvailable( return false; } - NSPasteboard* pb = GetPasteboard(); - NSArray* types = [pb types]; + // https://crbug.com/1016740#c21 + base::scoped_nsobject types([[GetPasteboard() types] retain]); // Safari only places RTF on the pasteboard, never HTML. We can convert RTF // to HTML, so the presence of either indicates success when looking for HTML. @@ -113,9 +112,8 @@ bool ClipboardMac::IsFormatAvailable( bool ClipboardMac::IsMarkedByOriginatorAsConfidential() const { DCHECK(CalledOnValidThread()); - NSPasteboard* pb = GetPasteboard(); NSPasteboardType type = - [pb availableTypeFromArray:@[ kUTTypeConfidentialData ]]; + [GetPasteboard() availableTypeFromArray:@[ kUTTypeConfidentialData ]]; if (type) return true; @@ -126,17 +124,14 @@ bool ClipboardMac::IsMarkedByOriginatorAsConfidential() const { void ClipboardMac::MarkAsConfidential() { DCHECK(CalledOnValidThread()); - NSPasteboard* pb = GetPasteboard(); - [pb addTypes:@[ kUTTypeConfidentialData ] owner:nil]; - [pb setData:nil forType:kUTTypeConfidentialData]; + [GetPasteboard() setData:nil forType:kUTTypeConfidentialData]; } void ClipboardMac::Clear(ClipboardBuffer buffer) { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); - NSPasteboard* pb = GetPasteboard(); - [pb declareTypes:@[] owner:nil]; + [GetPasteboard() declareTypes:@[] owner:nil]; } // |data_dst| is not used. It's only passed to be consistent with other @@ -144,10 +139,11 @@ void ClipboardMac::Clear(ClipboardBuffer buffer) { void ClipboardMac::ReadAvailableTypes( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const { + std::vector* types) const { DCHECK(CalledOnValidThread()); DCHECK(types); + NSPasteboard* pb = GetPasteboard(); types->clear(); if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer, data_dst)) @@ -159,12 +155,15 @@ void ClipboardMac::ReadAvailableTypes( if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst)) types->push_back(base::UTF8ToUTF16(kMimeTypeRTF)); if (IsFormatAvailable(ClipboardFormatType::GetFilenamesType(), buffer, - data_dst)) + data_dst)) { types->push_back(base::UTF8ToUTF16(kMimeTypeURIList)); - - NSPasteboard* pb = GetPasteboard(); - if (pb && [NSImage canInitWithPasteboard:pb]) + } else if (pb && [NSImage canInitWithPasteboard:pb]) { + // Finder Cmd+C places both file and icon onto the clipboard + // (http://crbug.com/553686), so ignore images if we have detected files. + // This means that if an image is present with file content, we will always + // ignore the image, but this matches observable Safari behavior. types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); + } if ([[pb types] containsObject:kWebCustomDataPboardType]) { NSData* data = [pb dataForType:kWebCustomDataPboardType]; @@ -175,17 +174,16 @@ void ClipboardMac::ReadAvailableTypes( // |data_dst| is not used. It's only passed to be consistent with other // platforms. -std::vector +std::vector ClipboardMac::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); - NSPasteboard* pb = GetPasteboard(); - NSArray* types = [pb types]; + NSArray* types = [GetPasteboard() types]; - std::vector type_names; + std::vector type_names; type_names.reserve([types count]); for (NSString* type in types) type_names.push_back(base::SysNSStringToUTF16(type)); @@ -196,12 +194,11 @@ ClipboardMac::ReadAvailablePlatformSpecificFormatNames( // platforms. void ClipboardMac::ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kText); - NSPasteboard* pb = GetPasteboard(); - NSString* contents = [pb stringForType:NSPasteboardTypeString]; + NSString* contents = [GetPasteboard() stringForType:NSPasteboardTypeString]; *result = base::SysNSStringToUTF16(contents); } @@ -214,8 +211,7 @@ void ClipboardMac::ReadAsciiText(ClipboardBuffer buffer, DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kText); - NSPasteboard* pb = GetPasteboard(); - NSString* contents = [pb stringForType:NSPasteboardTypeString]; + NSString* contents = [GetPasteboard() stringForType:NSPasteboardTypeString]; if (!contents) result->clear(); @@ -227,7 +223,7 @@ void ClipboardMac::ReadAsciiText(ClipboardBuffer buffer, // platforms. void ClipboardMac::ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -260,12 +256,11 @@ void ClipboardMac::ReadHTML(ClipboardBuffer buffer, void ClipboardMac::ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kSvg); - NSPasteboard* pb = GetPasteboard(); - NSString* contents = [pb stringForType:kImageSvg]; + NSString* contents = [GetPasteboard() stringForType:kImageSvg]; *result = base::SysNSStringToUTF16(contents); } @@ -294,9 +289,9 @@ void ClipboardMac::ReadImage(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardMac::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kCustomData); @@ -328,7 +323,7 @@ void ClipboardMac::ReadFilenames(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardMac::ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kBookmark); @@ -355,8 +350,7 @@ void ClipboardMac::ReadData(const ClipboardFormatType& format, std::string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kData); - NSPasteboard* pb = GetPasteboard(); - NSData* data = [pb dataForType:format.ToNSString()]; + NSData* data = [GetPasteboard() dataForType:format.ToNSString()]; if ([data length]) result->assign(static_cast([data bytes]), [data length]); } @@ -370,8 +364,7 @@ void ClipboardMac::WritePortableRepresentations( DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); - NSPasteboard* pb = GetPasteboard(); - [pb declareTypes:@[] owner:nil]; + [GetPasteboard() declareTypes:@[] owner:nil]; for (const auto& object : objects) DispatchPortableRepresentation(object.first, object.second); @@ -386,8 +379,7 @@ void ClipboardMac::WritePlatformRepresentations( DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); - NSPasteboard* pb = GetPasteboard(); - [pb declareTypes:@[] owner:nil]; + [GetPasteboard() declareTypes:@[] owner:nil]; DispatchPlatformRepresentations(std::move(platform_representations)); } @@ -395,9 +387,7 @@ void ClipboardMac::WritePlatformRepresentations( void ClipboardMac::WriteText(const char* text_data, size_t text_len) { std::string text_str(text_data, text_len); NSString* text = base::SysUTF8ToNSString(text_str); - NSPasteboard* pb = GetPasteboard(); - [pb addTypes:@[ NSPasteboardTypeString ] owner:nil]; - [pb setString:text forType:NSPasteboardTypeString]; + [GetPasteboard() setString:text forType:NSPasteboardTypeString]; } void ClipboardMac::WriteHTML(const char* markup_data, @@ -410,17 +400,13 @@ void ClipboardMac::WriteHTML(const char* markup_data, NSString* html_fragment = base::SysUTF8ToNSString(html_fragment_str); // TODO(avi): url_data? - NSPasteboard* pb = GetPasteboard(); - [pb addTypes:@[ NSHTMLPboardType ] owner:nil]; - [pb setString:html_fragment forType:NSHTMLPboardType]; + [GetPasteboard() setString:html_fragment forType:NSHTMLPboardType]; } void ClipboardMac::WriteSvg(const char* markup_data, size_t markup_len) { std::string svg_str(markup_data, markup_len); NSString* svg = base::SysUTF8ToNSString(svg_str); - NSPasteboard* pb = GetPasteboard(); - [pb addTypes:@[ kImageSvg ] owner:nil]; - [pb setString:svg forType:kImageSvg]; + [GetPasteboard() setString:svg forType:kImageSvg]; } void ClipboardMac::WriteRTF(const char* rtf_data, size_t data_len) { @@ -447,8 +433,7 @@ void ClipboardMac::WriteBookmark(const char* title_data, base::scoped_nsobject item( ClipboardUtil::PasteboardItemFromUrl(url, title)); - NSPasteboard* pb = GetPasteboard(); - ClipboardUtil::AddDataToPasteboard(pb, item); + ClipboardUtil::AddDataToPasteboard(GetPasteboard(), item); } void ClipboardMac::WriteBitmap(const SkBitmap& bitmap) { @@ -466,33 +451,27 @@ void ClipboardMac::WriteBitmap(const SkBitmap& bitmap) { // TODO (https://crbug.com/971916): Write NSImage directly to clipboard. // An API to ask the NSImage to write itself to the clipboard comes in 10.6 :( // For now, spit out the image as a TIFF. - NSPasteboard* pb = GetPasteboard(); - [pb addTypes:@[ NSTIFFPboardType ] owner:nil]; NSData* tiff_data = [image TIFFRepresentation]; LOG_IF(ERROR, tiff_data == nullptr) << "Failed to allocate image for clipboard"; if (tiff_data) { - [pb setData:tiff_data forType:NSTIFFPboardType]; + [GetPasteboard() setData:tiff_data forType:NSTIFFPboardType]; } } void ClipboardMac::WriteData(const ClipboardFormatType& format, const char* data_data, size_t data_len) { - NSPasteboard* pb = GetPasteboard(); - [pb addTypes:@[ format.ToNSString() ] owner:nil]; - [pb setData:[NSData dataWithBytes:data_data length:data_len] - forType:format.ToNSString()]; + [GetPasteboard() setData:[NSData dataWithBytes:data_data length:data_len] + forType:format.ToNSString()]; } // Write an extra flavor that signifies WebKit was the last to modify the // pasteboard. This flavor has no data. void ClipboardMac::WriteWebSmartPaste() { - NSPasteboard* pb = GetPasteboard(); NSString* format = ClipboardFormatType::GetWebKitSmartPasteType().ToNSString(); - [pb addTypes:@[ format ] owner:nil]; - [pb setData:nil forType:format]; + [GetPasteboard() setData:nil forType:format]; } SkBitmap ClipboardMac::ReadImageInternal(ClipboardBuffer buffer, @@ -505,6 +484,8 @@ SkBitmap ClipboardMac::ReadImageInternal(ClipboardBuffer buffer, // a blank image is better. base::scoped_nsobject image; @try { + // TODO(crbug.com/1175483): remove first branch of this code when + // ClipboardFilenames feature flag is removed. if ([[pasteboard types] containsObject:NSFilenamesPboardType]) { // -[NSImage initWithPasteboard:] gets confused with copies of a single // file from the Finder, so extract the path ourselves. @@ -521,7 +502,6 @@ SkBitmap ClipboardMac::ReadImageInternal(ClipboardBuffer buffer, } } @catch (id exception) { } - if (!image) return SkBitmap(); if ([[image representations] count] == 0u) diff --git a/chromium/ui/base/clipboard/clipboard_non_backed.cc b/chromium/ui/base/clipboard/clipboard_non_backed.cc index e9941077122..fcf249c6b32 100644 --- a/chromium/ui/base/clipboard/clipboard_non_backed.cc +++ b/chromium/ui/base/clipboard/clipboard_non_backed.cc @@ -34,7 +34,6 @@ #include "ui/base/data_transfer_policy/data_transfer_policy_controller.h" #include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/size.h" -#include "ui/ozone/buildflags.h" namespace ui { @@ -115,7 +114,7 @@ class ClipboardInternal { } // Reads text from the ClipboardData. - void ReadText(base::string16* result) const { + void ReadText(std::u16string* result) const { std::string utf8_result; ReadAsciiText(&utf8_result); *result = base::UTF8ToUTF16(utf8_result); @@ -136,7 +135,7 @@ class ClipboardInternal { } // Reads HTML from the ClipboardData. - void ReadHTML(base::string16* markup, + void ReadHTML(std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -159,7 +158,7 @@ class ClipboardInternal { } // Reads SVG from the ClipboardData. - void ReadSvg(base::string16* markup) const { + void ReadSvg(std::u16string* markup) const { markup->clear(); if (!HasFormat(ClipboardInternalFormat::kSvg)) @@ -197,8 +196,8 @@ class ClipboardInternal { } // Reads data of type |type| from the ClipboardData. - void ReadCustomData(const base::string16& type, - base::string16* result) const { + void ReadCustomData(const std::u16string& type, + std::u16string* result) const { result->clear(); const ClipboardData* data = GetData(); if (!HasFormat(ClipboardInternalFormat::kCustom)) @@ -214,7 +213,7 @@ class ClipboardInternal { } // Reads bookmark from the ClipboardData. - void ReadBookmark(base::string16* title, std::string* url) const { + void ReadBookmark(std::u16string* title, std::string* url) const { if (title) title->clear(); if (url) @@ -361,15 +360,6 @@ class ClipboardDataBuilder { ClipboardData* ClipboardDataBuilder::current_data_ = nullptr; -// linux-chromeos uses non-backed clipboard by default, but supports ozone x11 -// with flag --use-system-clipbboard. -#if !BUILDFLAG(IS_CHROMEOS_ASH) || !BUILDFLAG(OZONE_PLATFORM_X11) -// Clipboard factory method. -Clipboard* Clipboard::Create() { - return new ClipboardNonBacked; -} -#endif - // static ClipboardNonBacked* ClipboardNonBacked::GetForCurrentThread() { auto* clipboard = Clipboard::GetForCurrentThread(); @@ -469,7 +459,7 @@ void ClipboardNonBacked::Clear(ClipboardBuffer buffer) { void ClipboardNonBacked::ReadAvailableTypes( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const { + std::vector* types) const { DCHECK(CalledOnValidThread()); DCHECK(types); @@ -502,13 +492,13 @@ void ClipboardNonBacked::ReadAvailableTypes( } } -std::vector +std::vector ClipboardNonBacked::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { DCHECK(CalledOnValidThread()); - std::vector types; + std::vector types; if (!clipboard_internal_->IsReadAllowed(data_dst)) return types; @@ -537,7 +527,7 @@ ClipboardNonBacked::ReadAvailablePlatformSpecificFormatNames( void ClipboardNonBacked::ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); if (!clipboard_internal_->IsReadAllowed(data_dst)) @@ -569,7 +559,7 @@ void ClipboardNonBacked::ReadAsciiText(ClipboardBuffer buffer, void ClipboardNonBacked::ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -588,7 +578,7 @@ void ClipboardNonBacked::ReadHTML(ClipboardBuffer buffer, void ClipboardNonBacked::ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); if (!clipboard_internal_->IsReadAllowed(data_dst)) @@ -633,9 +623,9 @@ void ClipboardNonBacked::ReadImage(ClipboardBuffer buffer, } void ClipboardNonBacked::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); if (!clipboard_internal_->IsReadAllowed(data_dst)) @@ -667,7 +657,7 @@ void ClipboardNonBacked::ReadFilenames( } void ClipboardNonBacked::ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const { DCHECK(CalledOnValidThread()); diff --git a/chromium/ui/base/clipboard/clipboard_non_backed.h b/chromium/ui/base/clipboard/clipboard_non_backed.h index d14ff0ff67e..6194d63d2ad 100644 --- a/chromium/ui/base/clipboard/clipboard_non_backed.h +++ b/chromium/ui/base/clipboard/clipboard_non_backed.h @@ -59,25 +59,25 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const override; - std::vector ReadAvailablePlatformSpecificFormatNames( + std::vector* types) const override; + std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const override; void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const override; void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; @@ -85,14 +85,14 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardNonBacked const DataTransferEndpoint* data_dst, ReadImageCallback callback) const override; void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* result) const override; void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const override; void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, diff --git a/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc b/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc index e5989209bb5..963dbc4297f 100644 --- a/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc +++ b/chromium/ui/base/clipboard/clipboard_non_backed_unittest.cc @@ -5,9 +5,9 @@ #include "ui/base/clipboard/clipboard_non_backed.h" #include +#include #include -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" @@ -18,9 +18,9 @@ namespace ui { namespace { -std::vector UTF8Types(std::vector types) { +std::vector UTF8Types(std::vector types) { std::vector result; - for (const base::string16& type : types) + for (const std::u16string& type : types) result.push_back(base::UTF16ToUTF8(type)); return result; } @@ -99,7 +99,7 @@ TEST_F(ClipboardNonBackedTest, TextURIList) { auto data = std::make_unique(); data->set_bookmark_url("http://example.com"); clipboard()->WriteClipboardData(std::move(data)); - std::vector types; + std::vector types; clipboard()->ReadAvailableTypes(ClipboardBuffer::kCopyPaste, /*data_dst=*/nullptr, &types); diff --git a/chromium/ui/base/clipboard/clipboard_ozone.cc b/chromium/ui/base/clipboard/clipboard_ozone.cc index 782762a4064..cc838a70a2f 100644 --- a/chromium/ui/base/clipboard/clipboard_ozone.cc +++ b/chromium/ui/base/clipboard/clipboard_ozone.cc @@ -21,7 +21,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/timer/timer.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_buffer.h" #include "ui/base/clipboard/clipboard_constants.h" @@ -30,16 +29,9 @@ #include "ui/base/clipboard/custom_data_helper.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" #include "ui/gfx/codec/png_codec.h" -#include "ui/ozone/buildflags.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/platform_clipboard.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(OZONE_PLATFORM_X11) -#include "base/command_line.h" -#include "ui/base/clipboard/clipboard_non_backed.h" -#include "ui/base/ui_base_switches.h" -#endif - namespace ui { namespace { @@ -69,7 +61,6 @@ class StubPlatformClipboard : public PlatformClipboard { void RequestClipboardData( ClipboardBuffer buffer, const std::string& mime_type, - PlatformClipboard::DataMap* data_map, PlatformClipboard::RequestDataClosure callback) override { std::move(callback).Run({}); } @@ -218,10 +209,6 @@ class ClipboardOzone::AsyncClipboardOzone { std::move(quit_closure_).Run(); } - void FinishWithOptional(const base::Optional& result) { - Finish(result.value_or(Result{})); - } - base::WeakPtr> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -258,10 +245,9 @@ class ClipboardOzone::AsyncClipboardOzone { const std::string& mime_type) { using ReadRequest = Request; ReadRequest request; - PlatformClipboard::DataMap data_map; platform_clipboard_->RequestClipboardData( - buffer, mime_type, &data_map, - base::BindOnce(&ReadRequest::FinishWithOptional, request.GetWeakPtr())); + buffer, mime_type, + base::BindOnce(&ReadRequest::Finish, request.GetWeakPtr())); return request.TakeResultSync().release(); } @@ -296,26 +282,6 @@ class ClipboardOzone::AsyncClipboardOzone { DISALLOW_COPY_AND_ASSIGN(AsyncClipboardOzone); }; -// Uses the factory in the clipboard_linux otherwise. -// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. -// 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)) -// Clipboard factory method. -Clipboard* Clipboard::Create() { -// linux-chromeos uses non-backed clipboard by default, but supports ozone x11 -// with flag --use-system-clipbboard. -#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(OZONE_PLATFORM_X11) - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kUseSystemClipboard)) { - return new ClipboardNonBacked; - } -#endif - return new ClipboardOzone; -} -#endif - // ClipboardOzone implementation. ClipboardOzone::ClipboardOzone() { auto* platform_clipboard = @@ -365,7 +331,7 @@ void ClipboardOzone::Clear(ClipboardBuffer buffer) { void ClipboardOzone::ReadAvailableTypes( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const { + std::vector* types) const { DCHECK(CalledOnValidThread()); DCHECK(types); @@ -387,7 +353,7 @@ void ClipboardOzone::ReadAvailableTypes( } // TODO(crbug.com/1103194): |data_dst| should be supported. -std::vector +std::vector ClipboardOzone::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { @@ -395,7 +361,7 @@ ClipboardOzone::ReadAvailablePlatformSpecificFormatNames( std::vector mime_types = async_clipboard_ozone_->RequestMimeTypes(buffer); - std::vector types; + std::vector types; types.reserve(mime_types.size()); for (auto& mime_type : mime_types) types.push_back(base::UTF8ToUTF16(mime_type)); @@ -405,7 +371,7 @@ ClipboardOzone::ReadAvailablePlatformSpecificFormatNames( // TODO(crbug.com/1103194): |data_dst| should be supported. void ClipboardOzone::ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kText); @@ -430,7 +396,7 @@ void ClipboardOzone::ReadAsciiText(ClipboardBuffer buffer, // TODO(crbug.com/1103194): |data_dst| should be supported. void ClipboardOzone::ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -454,7 +420,7 @@ void ClipboardOzone::ReadHTML(ClipboardBuffer buffer, // TODO(crbug.com/1103194): |data_dst| should be supported. void ClipboardOzone::ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kSvg); @@ -486,9 +452,9 @@ void ClipboardOzone::ReadImage(ClipboardBuffer buffer, // TODO(crbug.com/1103194): |data_dst| should be supported. void ClipboardOzone::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kCustomData); @@ -512,7 +478,7 @@ void ClipboardOzone::ReadFilenames(ClipboardBuffer buffer, // TODO(crbug.com/1103194): |data_dst| should be supported. void ClipboardOzone::ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const { DCHECK(CalledOnValidThread()); // TODO(msisov): This was left NOTIMPLEMENTED() in all the Linux platforms. @@ -614,9 +580,8 @@ void ClipboardOzone::WriteBookmark(const char* title_data, const char* url_data, size_t url_len) { // Writes a Mozilla url (UTF16: URL, newline, title) - base::string16 bookmark = - base::UTF8ToUTF16(base::StringPiece(url_data, url_len)) + - base::ASCIIToUTF16("\n") + + std::u16string bookmark = + base::UTF8ToUTF16(base::StringPiece(url_data, url_len)) + u"\n" + base::UTF8ToUTF16(base::StringPiece(title_data, title_len)); std::vector data( diff --git a/chromium/ui/base/clipboard/clipboard_ozone.h b/chromium/ui/base/clipboard/clipboard_ozone.h index 70f0be365d0..fda6985b219 100644 --- a/chromium/ui/base/clipboard/clipboard_ozone.h +++ b/chromium/ui/base/clipboard/clipboard_ozone.h @@ -33,25 +33,25 @@ class ClipboardOzone : public Clipboard { void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const override; - std::vector ReadAvailablePlatformSpecificFormatNames( + std::vector* types) const override; + std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const override; void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const override; void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; @@ -59,14 +59,14 @@ class ClipboardOzone : public Clipboard { const DataTransferEndpoint* data_dst, ReadImageCallback callback) const override; void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* result) const override; void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const override; void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, diff --git a/chromium/ui/base/clipboard/clipboard_test_template.h b/chromium/ui/base/clipboard/clipboard_test_template.h index 533f759787e..d8f709df759 100644 --- a/chromium/ui/base/clipboard/clipboard_test_template.h +++ b/chromium/ui/base/clipboard/clipboard_test_template.h @@ -25,7 +25,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/pickle.h" #include "base/run_loop.h" -#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" @@ -94,8 +93,8 @@ class ClipboardTest : public PlatformTest { protected: Clipboard& clipboard() { return *clipboard_; } - std::vector GetAvailableTypes(ClipboardBuffer buffer) { - std::vector types; + std::vector GetAvailableTypes(ClipboardBuffer buffer) { + std::vector types; clipboard().ReadAvailableTypes(buffer, /* data_dst = */ nullptr, &types); return types; } @@ -117,6 +116,11 @@ class MockPolicyController : public DataTransferPolicyController { MOCK_METHOD2(IsClipboardReadAllowed, bool(const DataTransferEndpoint* const data_src, const DataTransferEndpoint* const data_dst)); + MOCK_METHOD4(PasteIfAllowed, + void(const DataTransferEndpoint* const data_src, + const DataTransferEndpoint* const data_dst, + content::WebContents* web_contents, + base::OnceCallback callback)); MOCK_METHOD3(IsDragDropAllowed, bool(const DataTransferEndpoint* const data_src, const DataTransferEndpoint* const data_dst, @@ -140,7 +144,7 @@ TYPED_TEST_SUITE(ClipboardTest, TypesToTest, NamesOfTypesToTest); TYPED_TEST(ClipboardTest, ClearTest) { { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); - clipboard_writer.WriteText(ASCIIToUTF16("clear me")); + clipboard_writer.WriteText(u"clear me"); } this->clipboard().Clear(ClipboardBuffer::kCopyPaste); @@ -156,7 +160,7 @@ TYPED_TEST(ClipboardTest, ClearTest) { } TYPED_TEST(ClipboardTest, TextTest) { - base::string16 text(ASCIIToUTF16("This is a base::string16!#$")), text_result; + std::u16string text(u"This is a std::u16string!#$"), text_result; std::string ascii_text; { @@ -169,8 +173,8 @@ TYPED_TEST(ClipboardTest, TextTest) { #if defined(USE_OZONE) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ !defined(OS_FUCHSIA) && !BUILDFLAG(IS_CHROMECAST) && \ !BUILDFLAG(IS_CHROMEOS_LACROS) - // TODO(https://crbug.com/1096425): remove this if condition. It seems like - // we have this condition working for Ozone/Linux, but not for X11/Linux. + // TODO(https://crbug.com/1096425): remove this if condition once Ozone is the + // only path in Linux builds. if (features::IsUsingOzonePlatform()) { EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste), Contains(ASCIIToUTF16(kMimeTypeTextUtf8))); @@ -195,8 +199,8 @@ TYPED_TEST(ClipboardTest, TextTest) { } TYPED_TEST(ClipboardTest, HTMLTest) { - base::string16 markup(ASCIIToUTF16("Hi!")), markup_result; - base::string16 plain(ASCIIToUTF16("Hi!")), plain_result; + std::u16string markup(u"Hi!"), markup_result; + std::u16string plain(u"Hi!"), plain_result; std::string url("http://www.example.com/"), url_result; { @@ -226,7 +230,7 @@ TYPED_TEST(ClipboardTest, HTMLTest) { } TYPED_TEST(ClipboardTest, SvgTest) { - base::string16 markup(ASCIIToUTF16(" ")); + std::u16string markup(u" "); { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); @@ -237,7 +241,7 @@ TYPED_TEST(ClipboardTest, SvgTest) { ClipboardFormatType::GetSvgType(), ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr)); - base::string16 markup_result; + std::u16string markup_result; this->clipboard().ReadSvg(ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &markup_result); @@ -279,8 +283,8 @@ TYPED_TEST(ClipboardTest, MultipleBufferTest) { return; } - base::string16 text(ASCIIToUTF16("Standard")), text_result; - base::string16 markup(ASCIIToUTF16("Selection")); + std::u16string text(u"Standard"), text_result; + std::u16string markup(u"Selection"); std::string url("http://www.example.com/"), url_result; { @@ -316,7 +320,7 @@ TYPED_TEST(ClipboardTest, MultipleBufferTest) { /* data_dst = */ nullptr, &text_result); EXPECT_EQ(text, text_result); - base::string16 markup_result; + std::u16string markup_result; uint32_t fragment_start; uint32_t fragment_end; this->clipboard().ReadHTML(ClipboardBuffer::kSelection, @@ -329,10 +333,9 @@ TYPED_TEST(ClipboardTest, MultipleBufferTest) { #endif TYPED_TEST(ClipboardTest, TrickyHTMLTest) { - base::string16 markup(ASCIIToUTF16("Bye!")), - markup_result; + std::u16string markup(u"Bye!"), markup_result; std::string url, url_result; - base::string16 plain(ASCIIToUTF16("Bye!")), plain_result; + std::u16string plain(u"Bye!"), plain_result; { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); @@ -363,7 +366,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) { - base::string16 markup(UTF8ToUTF16("

A \xc3\xb8 \xe6\xb0\xb4
")), + std::u16string markup(UTF8ToUTF16("
A \xc3\xb8 \xe6\xb0\xb4
")), markup_result; std::string url, url_result; @@ -397,7 +400,7 @@ TYPED_TEST(ClipboardTest, UnicodeHTMLTest) { // TODO(estade): Port the following test (decide what target we use for urls) #if !defined(OS_POSIX) || defined(OS_APPLE) TYPED_TEST(ClipboardTest, BookmarkTest) { - base::string16 title(ASCIIToUTF16("The Example Company")), title_result; + std::u16string title(u"The Example Company"), title_result; std::string url("http://www.example.com/"), url_result; { @@ -436,7 +439,7 @@ TYPED_TEST(ClipboardTest, FilenamesTest) { ClipboardFormatType::GetFilenamesType(), ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr)); - std::vector types; + std::vector types; this->clipboard().ReadAvailableTypes(ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &types); EXPECT_EQ(1u, types.size()); @@ -451,8 +454,8 @@ TYPED_TEST(ClipboardTest, FilenamesTest) { #endif // !defined(OS_ANDROID) TYPED_TEST(ClipboardTest, MultiFormatTest) { - base::string16 text(ASCIIToUTF16("Hi!")), text_result; - base::string16 markup(ASCIIToUTF16("Hi!
")), markup_result; + std::u16string text(u"Hi!"), text_result; + std::u16string markup(u"Hi!
"), markup_result; std::string url("http://www.example.com/"), url_result; std::string ascii_text; @@ -499,7 +502,7 @@ TYPED_TEST(ClipboardTest, MultiFormatTest) { } TYPED_TEST(ClipboardTest, URLTest) { - base::string16 url(ASCIIToUTF16("http://www.google.com/")); + std::u16string url(u"http://www.google.com/"); { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); @@ -516,7 +519,7 @@ TYPED_TEST(ClipboardTest, URLTest) { ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr)); #endif - base::string16 text_result; + std::u16string text_result; this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text_result); @@ -778,28 +781,28 @@ TYPED_TEST(ClipboardTest, MultipleDataTest) { #endif TYPED_TEST(ClipboardTest, ReadAvailablePlatformSpecificFormatNamesTest) { - base::string16 text = ASCIIToUTF16("Test String"); + std::u16string text = u"Test String"; std::string ascii_text; { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); clipboard_writer.WriteText(text); } - const std::vector raw_types = + const std::vector raw_types = this->clipboard().ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr); #if defined(OS_APPLE) - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("public.utf8-plain-text"))); - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("NSStringPboardType"))); + EXPECT_THAT(raw_types, Contains(u"public.utf8-plain-text")); + EXPECT_THAT(raw_types, Contains(u"NSStringPboardType")); EXPECT_EQ(raw_types.size(), static_cast(2)); // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete. #elif defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ !BUILDFLAG(IS_CHROMECAST) && !BUILDFLAG(IS_CHROMEOS_LACROS) EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeText))); - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("TEXT"))); - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("STRING"))); - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("UTF8_STRING"))); + EXPECT_THAT(raw_types, Contains(u"TEXT")); + EXPECT_THAT(raw_types, Contains(u"STRING")); + EXPECT_THAT(raw_types, Contains(u"UTF8_STRING")); #if defined(USE_OZONE) if (features::IsUsingOzonePlatform()) { EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeTextUtf8))); @@ -812,9 +815,9 @@ TYPED_TEST(ClipboardTest, ReadAvailablePlatformSpecificFormatNamesTest) { EXPECT_EQ(raw_types.size(), static_cast(4)); #endif // USE_X11 #elif defined(OS_WIN) - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("CF_UNICODETEXT"))); - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("CF_TEXT"))); - EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("CF_OEMTEXT"))); + EXPECT_THAT(raw_types, Contains(u"CF_UNICODETEXT")); + EXPECT_THAT(raw_types, Contains(u"CF_TEXT")); + EXPECT_THAT(raw_types, Contains(u"CF_OEMTEXT")); EXPECT_EQ(raw_types.size(), static_cast(3)); #elif defined(USE_AURA) || defined(OS_ANDROID) EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeText))); @@ -859,7 +862,7 @@ TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) { mojo_base::BigBuffer(text_span)); } - const std::vector raw_types = + const std::vector raw_types = this->clipboard().ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr); @@ -884,7 +887,7 @@ TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) { EXPECT_TRUE(this->clipboard().IsFormatAvailable( ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr)); - base::string16 text_result16; + std::u16string text_result16; this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text_result16); EXPECT_EQ(text_result16, base::ASCIIToUTF16(text)); @@ -901,12 +904,12 @@ TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) { TYPED_TEST(ClipboardTest, HyperlinkTest) { const std::string kTitle("The Company's \"home page\""); const std::string kUrl("http://www.example.com?x=3<=3#\"'<>"); - const base::string16 kExpectedHtml(UTF8ToUTF16( + const std::u16string kExpectedHtml(UTF8ToUTF16( "" "The <Example> Company's "home page"")); std::string url_result; - base::string16 html_result; + std::u16string html_result; { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); clipboard_writer.WriteHyperlink(ASCIIToUTF16(kTitle), kUrl); @@ -987,10 +990,10 @@ TYPED_TEST(ClipboardTest, HtmlTest) { TYPED_TEST(ClipboardTest, WriteEverything) { { ScopedClipboardWriter writer(ClipboardBuffer::kCopyPaste); - writer.WriteText(UTF8ToUTF16("foo")); - writer.WriteHTML(UTF8ToUTF16("foo"), "bar"); - writer.WriteBookmark(UTF8ToUTF16("foo"), "bar"); - writer.WriteHyperlink(ASCIIToUTF16("foo"), "bar"); + writer.WriteText(u"foo"); + writer.WriteHTML(u"foo", "bar"); + writer.WriteBookmark(u"foo", "bar"); + writer.WriteHyperlink(u"foo", "bar"); writer.WriteWebSmartPaste(); // Left out: WriteFile, WriteFiles, WriteBitmapFromPixels, WritePickledData. } @@ -1012,7 +1015,7 @@ TYPED_TEST(ClipboardTest, GetSequenceNumber) { { ScopedClipboardWriter writer(ClipboardBuffer::kCopyPaste); - writer.WriteText(UTF8ToUTF16("World")); + writer.WriteText(u"World"); } // On some platforms, the sequence number is updated by a UI callback so pump @@ -1030,17 +1033,17 @@ TYPED_TEST(ClipboardTest, GetSequenceNumber) { // vector. Not crashing = passing. TYPED_TEST(ClipboardTest, WriteTextEmptyParams) { ScopedClipboardWriter scw(ClipboardBuffer::kCopyPaste); - scw.WriteText(base::string16()); + scw.WriteText(std::u16string()); } TYPED_TEST(ClipboardTest, WriteHTMLEmptyParams) { ScopedClipboardWriter scw(ClipboardBuffer::kCopyPaste); - scw.WriteHTML(base::string16(), std::string()); + scw.WriteHTML(std::u16string(), std::string()); } TYPED_TEST(ClipboardTest, EmptySvgTest) { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); - clipboard_writer.WriteSvg(base::string16()); + clipboard_writer.WriteSvg(std::u16string()); } TYPED_TEST(ClipboardTest, WriteRTFEmptyParams) { @@ -1050,12 +1053,12 @@ TYPED_TEST(ClipboardTest, WriteRTFEmptyParams) { TYPED_TEST(ClipboardTest, WriteBookmarkEmptyParams) { ScopedClipboardWriter scw(ClipboardBuffer::kCopyPaste); - scw.WriteBookmark(base::string16(), std::string()); + scw.WriteBookmark(std::u16string(), std::string()); } TYPED_TEST(ClipboardTest, WriteHyperlinkEmptyParams) { ScopedClipboardWriter scw(ClipboardBuffer::kCopyPaste); - scw.WriteHyperlink(base::string16(), std::string()); + scw.WriteHyperlink(std::u16string(), std::string()); } TYPED_TEST(ClipboardTest, WritePickledData) { @@ -1075,7 +1078,7 @@ TYPED_TEST(ClipboardTest, WriteImageEmptyParams) { // restrict the clipboard data. TYPED_TEST(ClipboardTest, PolicyAllowDataRead) { auto policy_controller = std::make_unique(); - const base::string16 kTestText(base::UTF8ToUTF16("World")); + const std::u16string kTestText(u"World"); { ScopedClipboardWriter writer( ClipboardBuffer::kCopyPaste, @@ -1084,7 +1087,7 @@ TYPED_TEST(ClipboardTest, PolicyAllowDataRead) { } EXPECT_CALL(*policy_controller, IsClipboardReadAllowed) .WillRepeatedly(testing::Return(true)); - base::string16 read_result; + std::u16string read_result; this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &read_result); ::testing::Mock::VerifyAndClearExpectations(policy_controller.get()); @@ -1095,7 +1098,7 @@ TYPED_TEST(ClipboardTest, PolicyAllowDataRead) { // restricted it. TYPED_TEST(ClipboardTest, PolicyDisallow_ReadText) { auto policy_controller = std::make_unique(); - const base::string16 kTestText(base::UTF8ToUTF16("World")); + const std::u16string kTestText(u"World"); { ScopedClipboardWriter writer( ClipboardBuffer::kCopyPaste, @@ -1104,11 +1107,11 @@ TYPED_TEST(ClipboardTest, PolicyDisallow_ReadText) { } EXPECT_CALL(*policy_controller, IsClipboardReadAllowed) .WillRepeatedly(testing::Return(false)); - base::string16 read_result; + std::u16string read_result; this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &read_result); ::testing::Mock::VerifyAndClearExpectations(policy_controller.get()); - EXPECT_EQ(base::string16(), read_result); + EXPECT_EQ(std::u16string(), read_result); } TYPED_TEST(ClipboardTest, PolicyDisallow_ReadImage) { diff --git a/chromium/ui/base/clipboard/clipboard_util_win.cc b/chromium/ui/base/clipboard/clipboard_util_win.cc index 9a212a9f485..747923cb6d4 100644 --- a/chromium/ui/base/clipboard/clipboard_util_win.cc +++ b/chromium/ui/base/clipboard/clipboard_util_win.cc @@ -50,7 +50,7 @@ bool GetData(IDataObject* data_object, bool GetUrlFromHDrop(IDataObject* data_object, GURL* url, - base::string16* title) { + std::u16string* title) { DCHECK(data_object && url && title); bool success = false; @@ -82,14 +82,14 @@ bool GetUrlFromHDrop(IDataObject* data_object, return success; } -void SplitUrlAndTitle(const base::string16& str, +void SplitUrlAndTitle(const std::u16string& str, GURL* url, - base::string16* title) { + std::u16string* title) { DCHECK(url && title); size_t newline_pos = str.find('\n'); - if (newline_pos != base::string16::npos) { - *url = GURL(base::string16(str, 0, newline_pos)); - title->assign(str, newline_pos + 1, base::string16::npos); + if (newline_pos != std::u16string::npos) { + *url = GURL(std::u16string(str, 0, newline_pos)); + title->assign(str, newline_pos + 1, std::u16string::npos); } else { *url = GURL(str); title->assign(str); @@ -492,7 +492,7 @@ bool ClipboardUtil::HasPlainText(IDataObject* data_object) { bool ClipboardUtil::GetUrl(IDataObject* data_object, GURL* url, - base::string16* title, + std::u16string* title, bool convert_filenames) { DCHECK(data_object && url && title); if (!HasUrl(data_object, convert_filenames)) @@ -686,7 +686,7 @@ bool ClipboardUtil::GetVirtualFilesAsTempFiles( } bool ClipboardUtil::GetPlainText(IDataObject* data_object, - base::string16* plain_text) { + std::u16string* plain_text) { DCHECK(data_object && plain_text); if (!HasPlainText(data_object)) return false; @@ -715,7 +715,7 @@ bool ClipboardUtil::GetPlainText(IDataObject* data_object, // If a file is dropped on the window, it does not provide either of the // plain text formats, so here we try to forcibly get a url. GURL url; - base::string16 title; + std::u16string title; if (GetUrl(data_object, &url, &title, false)) { *plain_text = base::UTF8ToUTF16(url.spec()); return true; @@ -724,7 +724,8 @@ bool ClipboardUtil::GetPlainText(IDataObject* data_object, } bool ClipboardUtil::GetHtml(IDataObject* data_object, - base::string16* html, std::string* base_url) { + std::u16string* html, + std::string* base_url) { DCHECK(data_object && html && base_url); STGMEDIUM store; @@ -796,7 +797,7 @@ bool ClipboardUtil::GetFileContents(IDataObject* data_object, bool ClipboardUtil::GetWebCustomData( IDataObject* data_object, - std::unordered_map* custom_data) { + std::unordered_map* custom_data) { DCHECK(data_object && custom_data); if (!HasData(data_object, ClipboardFormatType::GetWebCustomDataType())) @@ -815,7 +816,6 @@ bool ClipboardUtil::GetWebCustomData( return false; } - // HtmlToCFHtml and CFHtmlToHtml are based on similar methods in // WebCore/platform/win/ClipboardUtilitiesWin.cpp. /* diff --git a/chromium/ui/base/clipboard/clipboard_util_win.h b/chromium/ui/base/clipboard/clipboard_util_win.h index 3e17b4c0133..d7ffbd69d9d 100644 --- a/chromium/ui/base/clipboard/clipboard_util_win.h +++ b/chromium/ui/base/clipboard/clipboard_util_win.h @@ -15,7 +15,6 @@ #include "base/callback_forward.h" #include "base/component_export.h" #include "base/files/file_path.h" -#include "base/strings/string16.h" #include "ui/base/clipboard/file_info.h" class GURL; @@ -42,7 +41,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardUtil { // Only returns true if url->is_valid() is true. static bool GetUrl(IDataObject* data_object, GURL* url, - base::string16* title, + std::u16string* title, bool convert_filenames); // Only returns true if |*filenames| is not empty. static bool GetFilenames(IDataObject* data_object, @@ -78,9 +77,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardUtil { callback); static bool GetPlainText(IDataObject* data_object, - base::string16* plain_text); + std::u16string* plain_text); static bool GetHtml(IDataObject* data_object, - base::string16* text_html, + std::u16string* text_html, std::string* base_url); static bool GetFileContents(IDataObject* data_object, std::wstring* filename, @@ -91,7 +90,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardUtil { // strings from web content. static bool GetWebCustomData( IDataObject* data_object, - std::unordered_map* custom_data); + std::unordered_map* custom_data); // Helper method for converting between MS CF_HTML format and plain // text/html. diff --git a/chromium/ui/base/clipboard/clipboard_win.cc b/chromium/ui/base/clipboard/clipboard_win.cc index 84071dbb29c..751f40e1d79 100644 --- a/chromium/ui/base/clipboard/clipboard_win.cc +++ b/chromium/ui/base/clipboard/clipboard_win.cc @@ -195,10 +195,10 @@ void MakeBitmapOpaque(SkPixmap* pixmap) { } } -void ParseBookmarkClipboardFormat(const base::string16& bookmark, - base::string16* title, +void ParseBookmarkClipboardFormat(const std::u16string& bookmark, + std::u16string* title, std::string* url) { - const base::string16 kDelim = base::ASCIIToUTF16("\r\n"); + const std::u16string kDelim = u"\r\n"; const size_t title_end = bookmark.find_first_of(kDelim); if (title) @@ -206,9 +206,9 @@ void ParseBookmarkClipboardFormat(const base::string16& bookmark, if (url) { const size_t url_start = bookmark.find_first_not_of(kDelim, title_end); - if (url_start != base::string16::npos) { + if (url_start != std::u16string::npos) { *url = - base::UTF16ToUTF8(bookmark.substr(url_start, base::string16::npos)); + base::UTF16ToUTF8(bookmark.substr(url_start, std::u16string::npos)); } } } @@ -299,7 +299,7 @@ void ClipboardWin::Clear(ClipboardBuffer buffer) { void ClipboardWin::ReadAvailableTypes( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const { + std::vector* types) const { DCHECK(types); types->clear(); @@ -333,7 +333,7 @@ void ClipboardWin::ReadAvailableTypes( // |data_dst| is not used. It's only passed to be consistent with other // platforms. -std::vector +std::vector ClipboardWin::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { @@ -341,7 +341,7 @@ ClipboardWin::ReadAvailablePlatformSpecificFormatNames( if (!count) return {}; - std::vector types; + std::vector types; types.reserve(count); ScopedClipboard clipboard; @@ -363,7 +363,7 @@ ClipboardWin::ReadAvailablePlatformSpecificFormatNames( // platforms. void ClipboardWin::ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kText); if (!result) { @@ -382,8 +382,8 @@ void ClipboardWin::ReadText(ClipboardBuffer buffer, if (!data) return; - result->assign(static_cast(::GlobalLock(data)), - ::GlobalSize(data) / sizeof(base::char16)); + result->assign(static_cast(::GlobalLock(data)), + ::GlobalSize(data) / sizeof(char16_t)); ::GlobalUnlock(data); TrimAfterNull(result); } @@ -421,7 +421,7 @@ void ClipboardWin::ReadAsciiText(ClipboardBuffer buffer, // platforms. void ClipboardWin::ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -482,14 +482,14 @@ void ClipboardWin::ReadHTML(ClipboardBuffer buffer, // platforms. void ClipboardWin::ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kSvg); std::string data; ReadData(ClipboardFormatType::GetSvgType(), data_dst, &data); - result->assign(reinterpret_cast(data.data()), - data.size() / sizeof(base::char16)); + result->assign(reinterpret_cast(data.data()), + data.size() / sizeof(char16_t)); TrimAfterNull(result); } @@ -518,9 +518,9 @@ void ClipboardWin::ReadImage(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardWin::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); RecordRead(ClipboardFormatMetric::kCustomData); @@ -610,7 +610,7 @@ void ClipboardWin::ReadFilenames(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardWin::ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const { RecordRead(ClipboardFormatMetric::kBookmark); if (title) @@ -629,8 +629,8 @@ void ClipboardWin::ReadBookmark(const DataTransferEndpoint* data_dst, if (!data) return; - base::string16 bookmark(static_cast(::GlobalLock(data)), - ::GlobalSize(data) / sizeof(base::char16)); + std::u16string bookmark(static_cast(::GlobalLock(data)), + ::GlobalSize(data) / sizeof(char16_t)); ::GlobalUnlock(data); TrimAfterNull(&bookmark); @@ -697,7 +697,7 @@ void ClipboardWin::WritePlatformRepresentations( } void ClipboardWin::WriteText(const char* text_data, size_t text_len) { - base::string16 text; + std::u16string text; base::UTF8ToUTF16(text_data, text_len, &text); HGLOBAL glob = CreateGlobalData(text); @@ -721,7 +721,7 @@ void ClipboardWin::WriteHTML(const char* markup_data, } void ClipboardWin::WriteSvg(const char* markup_data, size_t markup_len) { - base::string16 markup; + std::u16string markup; base::UTF8ToUTF16(markup_data, markup_len, &markup); HGLOBAL glob = CreateGlobalData(markup); @@ -747,7 +747,7 @@ void ClipboardWin::WriteBookmark(const char* title_data, bookmark.append(1, L'\n'); bookmark.append(url_data, url_len); - base::string16 wide_bookmark = base::UTF8ToUTF16(bookmark); + std::u16string wide_bookmark = base::UTF8ToUTF16(bookmark); HGLOBAL glob = CreateGlobalData(wide_bookmark); WriteToClipboard(ClipboardFormatType::GetUrlType(), glob); diff --git a/chromium/ui/base/clipboard/clipboard_win.h b/chromium/ui/base/clipboard/clipboard_win.h index a3129d23e57..e5d613250c0 100644 --- a/chromium/ui/base/clipboard/clipboard_win.h +++ b/chromium/ui/base/clipboard/clipboard_win.h @@ -43,25 +43,25 @@ class ClipboardWin : public Clipboard { void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const override; - std::vector ReadAvailablePlatformSpecificFormatNames( + std::vector* types) const override; + std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const override; void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const override; void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; @@ -69,14 +69,14 @@ class ClipboardWin : public Clipboard { const DataTransferEndpoint* data_dst, ReadImageCallback callback) const override; void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* result) const override; void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const override; void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, diff --git a/chromium/ui/base/clipboard/clipboard_x11.cc b/chromium/ui/base/clipboard/clipboard_x11.cc index 767819294ad..3c83fe820b7 100644 --- a/chromium/ui/base/clipboard/clipboard_x11.cc +++ b/chromium/ui/base/clipboard/clipboard_x11.cc @@ -4,474 +4,33 @@ #include "ui/base/clipboard/clipboard_x11.h" -#include - +#include #include -#include #include -#include +#include +#include "base/bind.h" #include "base/containers/contains.h" -#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ref_counted_memory.h" -#include "base/memory/singleton.h" -#include "base/metrics/histogram_macros.h" -#include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/clipboard/clipboard_buffer.h" #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/clipboard/clipboard_monitor.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" -#include "ui/base/nine_image_painter_factory.h" -#include "ui/base/ui_base_features.h" -#include "ui/base/x/selection_owner.h" -#include "ui/base/x/selection_requestor.h" -#include "ui/base/x/selection_utils.h" -#include "ui/base/x/x11_util.h" +#include "ui/base/x/x11_clipboard_helper.h" #include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/x/connection.h" -#include "ui/gfx/x/event.h" -#include "ui/gfx/x/x11_atom_cache.h" -#include "ui/gfx/x/x11_window_event_manager.h" -#include "ui/gfx/x/xfixes.h" -#include "ui/gfx/x/xproto.h" -#include "ui/gfx/x/xproto_util.h" namespace ui { -namespace { - -const char kClipboard[] = "CLIPBOARD"; -const char kClipboardManager[] = "CLIPBOARD_MANAGER"; - -/////////////////////////////////////////////////////////////////////////////// - -// Uses the XFixes API to provide sequence numbers for GetSequenceNumber(). -class SelectionChangeObserver : public x11::EventObserver { - public: - static SelectionChangeObserver* GetInstance(); - - uint64_t clipboard_sequence_number() const { - return clipboard_sequence_number_; - } - uint64_t primary_sequence_number() const { return primary_sequence_number_; } - - private: - friend struct base::DefaultSingletonTraits; - - SelectionChangeObserver(); - ~SelectionChangeObserver() override; - - // x11::EventObserver: - void OnEvent(const x11::Event& xev) override; - - x11::Atom clipboard_atom_{}; - uint64_t clipboard_sequence_number_{}; - uint64_t primary_sequence_number_{}; - - DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver); -}; - -SelectionChangeObserver::SelectionChangeObserver() { - auto* connection = x11::Connection::Get(); - auto& xfixes = connection->xfixes(); - // Let the server know the client version. No need to sync since we don't - // care what version is running on the server. - xfixes.QueryVersion({x11::XFixes::major_version, x11::XFixes::minor_version}); - if (!xfixes.present()) - return; - - clipboard_atom_ = x11::GetAtom(kClipboard); - auto mask = x11::XFixes::SelectionEventMask::SetSelectionOwner | - x11::XFixes::SelectionEventMask::SelectionWindowDestroy | - x11::XFixes::SelectionEventMask::SelectionClientClose; - xfixes.SelectSelectionInput({GetX11RootWindow(), clipboard_atom_, mask}); - // This seems to be semi-optional. For some reason, registering for any - // selection notify events seems to subscribe us to events for both the - // primary and the clipboard buffers. Register anyway just to be safe. - xfixes.SelectSelectionInput({GetX11RootWindow(), x11::Atom::PRIMARY, mask}); - - connection->AddEventObserver(this); -} - -// We are a singleton; we will outlive the event source. -SelectionChangeObserver::~SelectionChangeObserver() = default; - -SelectionChangeObserver* SelectionChangeObserver::GetInstance() { - return base::Singleton::get(); -} - -void SelectionChangeObserver::OnEvent(const x11::Event& xev) { - auto* ev = xev.As(); - if (!ev) - return; - - if (static_cast(ev->selection) == clipboard_atom_) { - clipboard_sequence_number_++; - ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged(); - } else if (ev->selection == x11::Atom::PRIMARY) { - primary_sequence_number_++; - } else { - DLOG(ERROR) << "Unexpected selection atom: " - << static_cast(ev->selection); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -// Represents a list of possible return types. Copy constructable. -class TargetList { - public: - using AtomVector = std::vector; - - explicit TargetList(const AtomVector& target_list); - - const AtomVector& target_list() { return target_list_; } - - bool ContainsText() const; - bool ContainsFormat(const ClipboardFormatType& format_type) const; - bool ContainsAtom(x11::Atom atom) const; - - private: - AtomVector target_list_; -}; - -TargetList::TargetList(const AtomVector& target_list) - : target_list_(target_list) {} - -bool TargetList::ContainsText() const { - std::vector atoms = GetTextAtomsFrom(); - for (const auto& atom : atoms) { - if (ContainsAtom(atom)) - return true; - } - - return false; -} - -bool TargetList::ContainsFormat(const ClipboardFormatType& format_type) const { - x11::Atom atom = x11::GetAtom(format_type.GetName().c_str()); - return ContainsAtom(atom); -} - -bool TargetList::ContainsAtom(x11::Atom atom) const { - return base::Contains(target_list_, atom); -} - -x11::Window GetSelectionOwner(x11::Atom selection) { - auto response = x11::Connection::Get()->GetSelectionOwner({selection}).Sync(); - return response ? response->owner : x11::Window::None; -} - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// ClipboardX11::X11Details - -// Private implementation of our X11 integration. Keeps X11 headers out of the -// majority of chrome, which break badly. -class ClipboardX11::X11Details : public x11::EventObserver { - public: - X11Details(); - ~X11Details() override; - - // Returns the X11 selection atom that we pass to various XSelection functions - // for the given buffer. - x11::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const; - - // Returns the X11 selection atom that we pass to various XSelection functions - // for ClipboardBuffer::kCopyPaste. - x11::Atom GetCopyPasteSelection() const; - - // Finds the SelectionFormatMap for the incoming selection atom. - const SelectionFormatMap& LookupStorageForAtom(x11::Atom atom); - - // As we need to collect all the data types before we tell X11 that we own a - // particular selection, we create a temporary clipboard mapping that - // InsertMapping writes to. Then we commit it in TakeOwnershipOfSelection, - // where we save it in one of the clipboard data slots. - void CreateNewClipboardData(); - - // Inserts a mapping into clipboard_data_. - void InsertMapping(const std::string& key, - const scoped_refptr& memory); - - // Moves the temporary |clipboard_data_| to the long term data storage for - // |buffer|. - void TakeOwnershipOfSelection(ClipboardBuffer buffer); - - // Returns the first of |types| offered by the current selection holder in - // |data_out|, or returns nullptr if none of those types are available. - // - // If the selection holder is us, this call is synchronous and we pull - // the data out of |clipboard_selection_| or |primary_selection_|. If the - // selection holder is some other window, we spin up a nested run loop - // and do the asynchronous dance with whatever application is holding the - // selection. - SelectionData RequestAndWaitForTypes(ClipboardBuffer buffer, - const std::vector& types); - - // Retrieves the list of possible data types the current clipboard owner has. - // - // If the selection holder is us, this is synchronous, otherwise this runs a - // blocking message loop. - TargetList WaitAndGetTargetsList(ClipboardBuffer buffer); - - // Returns a list of all text atoms that we handle. - std::vector GetTextAtoms() const; - - // Returns a vector with a |format| converted to an X11 atom. - std::vector GetAtomsForFormat(const ClipboardFormatType& format); - - // Clears a certain clipboard buffer, whether we own it or not. - void Clear(ClipboardBuffer buffer); - - // If we own the CLIPBOARD selection, requests the clipboard manager to take - // ownership of it. - void StoreCopyPasteDataAndWait(); - - private: - // x11::EventObserver: - void OnEvent(const x11::Event& xev) override; - - // Our X11 state. - x11::Connection* connection_; - x11::Window x_root_window_; - - // Input-only window used as a selection owner. - x11::Window x_window_; - - // Events selected on |x_window_|. - std::unique_ptr x_window_events_; - - // Object which requests and receives selection data. - SelectionRequestor selection_requestor_; - - // Temporary target map that we write to during DispatchObects. - SelectionFormatMap clipboard_data_; - - // Objects which offer selection data to other windows. - SelectionOwner clipboard_owner_; - SelectionOwner primary_owner_; - - DISALLOW_COPY_AND_ASSIGN(X11Details); -}; - -ClipboardX11::X11Details::X11Details() - : connection_(x11::Connection::Get()), - x_root_window_(ui::GetX11RootWindow()), - x_window_(x11::CreateDummyWindow("Chromium Clipboard Window")), - selection_requestor_(x_window_, this), - clipboard_owner_(connection_, x_window_, x11::GetAtom(kClipboard)), - primary_owner_(connection_, x_window_, x11::Atom::PRIMARY) { - x11::SetStringProperty(x_window_, x11::Atom::WM_NAME, x11::Atom::STRING, - "Chromium clipboard"); - x_window_events_ = std::make_unique( - x_window_, x11::EventMask::PropertyChange); - - connection_->AddEventObserver(this); -} - -ClipboardX11::X11Details::~X11Details() { - connection_->RemoveEventObserver(this); - connection_->DestroyWindow({x_window_}); -} - -x11::Atom ClipboardX11::X11Details::LookupSelectionForClipboardBuffer( - ClipboardBuffer buffer) const { - if (buffer == ClipboardBuffer::kCopyPaste) - return GetCopyPasteSelection(); - - return x11::Atom::PRIMARY; -} - -x11::Atom ClipboardX11::X11Details::GetCopyPasteSelection() const { - return x11::GetAtom(kClipboard); -} - -const SelectionFormatMap& ClipboardX11::X11Details::LookupStorageForAtom( - x11::Atom atom) { - if (atom == x11::Atom::PRIMARY) - return primary_owner_.selection_format_map(); - - DCHECK_EQ(GetCopyPasteSelection(), atom); - return clipboard_owner_.selection_format_map(); -} - -void ClipboardX11::X11Details::CreateNewClipboardData() { - clipboard_data_ = SelectionFormatMap(); -} - -void ClipboardX11::X11Details::InsertMapping( - const std::string& key, - const scoped_refptr& memory) { - x11::Atom atom_key = x11::GetAtom(key.c_str()); - clipboard_data_.Insert(atom_key, memory); -} - -void ClipboardX11::X11Details::TakeOwnershipOfSelection( - ClipboardBuffer buffer) { - if (buffer == ClipboardBuffer::kCopyPaste) - return clipboard_owner_.TakeOwnershipOfSelection(clipboard_data_); - else - return primary_owner_.TakeOwnershipOfSelection(clipboard_data_); -} - -SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes( - ClipboardBuffer buffer, - const std::vector& types) { - x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); - if (GetSelectionOwner(selection_name) == x_window_) { - // We can local fastpath instead of playing the nested run loop game - // with the X server. - const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); - - for (const auto& type : types) { - auto format_map_it = format_map.find(type); - if (format_map_it != format_map.end()) - return SelectionData(format_map_it->first, format_map_it->second); - } - } else { - TargetList targets = WaitAndGetTargetsList(buffer); - - x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); - std::vector intersection; - GetAtomIntersection(types, targets.target_list(), &intersection); - return selection_requestor_.RequestAndWaitForTypes(selection_name, - intersection); - } - - return SelectionData(); -} - -TargetList ClipboardX11::X11Details::WaitAndGetTargetsList( - ClipboardBuffer buffer) { - x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); - std::vector out; - if (GetSelectionOwner(selection_name) == x_window_) { - // We can local fastpath and return the list of local targets. - const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); - - for (const auto& format : format_map) - out.push_back(format.first); - } else { - std::vector data; - x11::Atom out_type = x11::Atom::None; - - if (selection_requestor_.PerformBlockingConvertSelection( - selection_name, x11::GetAtom(kTargets), &data, &out_type)) { - // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) - if (out_type == x11::Atom::ATOM || out_type == x11::GetAtom(kTargets)) { - const x11::Atom* atom_array = - reinterpret_cast(data.data()); - for (size_t i = 0; i < data.size() / sizeof(x11::Atom); ++i) - out.push_back(atom_array[i]); - } - } else { - // There was no target list. Most Java apps doesn't offer a TARGETS list, - // even though they AWT to. They will offer individual text types if you - // ask. If this is the case we attempt to make sense of the contents as - // text. This is pretty unfortunate since it means we have to actually - // copy the data to see if it is available, but at least this path - // shouldn't be hit for conforming programs. - std::vector types = GetTextAtoms(); - for (const auto& text_atom : types) { - x11::Atom type = x11::Atom::None; - if (selection_requestor_.PerformBlockingConvertSelection( - selection_name, text_atom, nullptr, &type) && - type == text_atom) { - out.push_back(text_atom); - } - } - } - } - - return TargetList(out); -} - -std::vector ClipboardX11::X11Details::GetTextAtoms() const { - return GetTextAtomsFrom(); -} - -std::vector ClipboardX11::X11Details::GetAtomsForFormat( - const ClipboardFormatType& format) { - return {x11::GetAtom(format.GetName().c_str())}; -} - -void ClipboardX11::X11Details::Clear(ClipboardBuffer buffer) { - if (buffer == ClipboardBuffer::kCopyPaste) - clipboard_owner_.ClearSelectionOwner(); - else - primary_owner_.ClearSelectionOwner(); -} - -void ClipboardX11::X11Details::StoreCopyPasteDataAndWait() { - x11::Atom selection = GetCopyPasteSelection(); - if (GetSelectionOwner(selection) != x_window_) - return; - - x11::Atom clipboard_manager_atom = x11::GetAtom(kClipboardManager); - if (GetSelectionOwner(clipboard_manager_atom) == x11::Window::None) - return; - - const SelectionFormatMap& format_map = LookupStorageForAtom(selection); - if (format_map.size() == 0) - return; - std::vector targets = format_map.GetTypes(); - - base::TimeTicks start = base::TimeTicks::Now(); - selection_requestor_.PerformBlockingConvertSelectionWithParameter( - x11::GetAtom(kClipboardManager), x11::GetAtom(kSaveTargets), targets); - UMA_HISTOGRAM_TIMES("Clipboard.X11StoreCopyPasteDuration", - base::TimeTicks::Now() - start); -} - -void ClipboardX11::X11Details::OnEvent(const x11::Event& xev) { - if (auto* request = xev.As()) { - if (request->owner != x_window_) - return; - if (request->selection == x11::Atom::PRIMARY) { - primary_owner_.OnSelectionRequest(*request); - } else { - // We should not get requests for the CLIPBOARD_MANAGER selection - // because we never take ownership of it. - DCHECK_EQ(GetCopyPasteSelection(), request->selection); - clipboard_owner_.OnSelectionRequest(*request); - } - } else if (auto* notify = xev.As()) { - if (notify->requestor == x_window_) - selection_requestor_.OnSelectionNotify(*notify); - } else if (auto* clear = xev.As()) { - if (clear->owner != x_window_) - return; - if (clear->selection == x11::Atom::PRIMARY) { - primary_owner_.OnSelectionClear(*clear); - } else { - // We should not get requests for the CLIPBOARD_MANAGER selection - // because we never take ownership of it. - DCHECK_EQ(GetCopyPasteSelection(), clear->selection); - clipboard_owner_.OnSelectionClear(*clear); - } - } else if (auto* prop = xev.As()) { - if (primary_owner_.CanDispatchPropertyEvent(*prop)) - primary_owner_.OnPropertyEvent(*prop); - if (clipboard_owner_.CanDispatchPropertyEvent(*prop)) - clipboard_owner_.OnPropertyEvent(*prop); - if (selection_requestor_.CanDispatchPropertyEvent(*prop)) - selection_requestor_.OnPropertyEvent(*prop); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// ClipboardX11 - -ClipboardX11::ClipboardX11() : x11_details_(new X11Details) { +ClipboardX11::ClipboardX11() + : x_clipboard_helper_(std::make_unique( + base::BindRepeating(&ClipboardX11::OnSelectionChanged, + base::Unretained(this)))) { DCHECK(CalledOnValidThread()); } @@ -481,7 +40,7 @@ ClipboardX11::~ClipboardX11() { void ClipboardX11::OnPreShutdown() { DCHECK(CalledOnValidThread()); - x11_details_->StoreCopyPasteDataAndWait(); + x_clipboard_helper_->StoreCopyPasteDataAndWait(); } DataTransferEndpoint* ClipboardX11::GetSource(ClipboardBuffer buffer) const { @@ -492,10 +51,8 @@ DataTransferEndpoint* ClipboardX11::GetSource(ClipboardBuffer buffer) const { uint64_t ClipboardX11::GetSequenceNumber(ClipboardBuffer buffer) const { DCHECK(CalledOnValidThread()); - if (buffer == ClipboardBuffer::kCopyPaste) - return SelectionChangeObserver::GetInstance()->clipboard_sequence_number(); - else - return SelectionChangeObserver::GetInstance()->primary_sequence_number(); + return buffer == ClipboardBuffer::kCopyPaste ? clipboard_sequence_number_ + : primary_sequence_number_; } // |data_dst| is not used. It's only passed to be consistent with other @@ -506,19 +63,13 @@ bool ClipboardX11::IsFormatAvailable( const DataTransferEndpoint* data_dst) const { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); - - TargetList target_list = x11_details_->WaitAndGetTargetsList(buffer); - if (format == ClipboardFormatType::GetPlainTextType() || - format == ClipboardFormatType::GetUrlType()) { - return target_list.ContainsText(); - } - return target_list.ContainsFormat(format); + return x_clipboard_helper_->IsFormatAvailable(buffer, format); } void ClipboardX11::Clear(ClipboardBuffer buffer) { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); - x11_details_->Clear(buffer); + x_clipboard_helper_->Clear(buffer); data_src_[buffer].reset(); } @@ -527,73 +78,50 @@ void ClipboardX11::Clear(ClipboardBuffer buffer) { void ClipboardX11::ReadAvailableTypes( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const { + std::vector* types) const { DCHECK(CalledOnValidThread()); DCHECK(types); - TargetList target_list = x11_details_->WaitAndGetTargetsList(buffer); - types->clear(); - - if (target_list.ContainsText()) - types->push_back(base::UTF8ToUTF16(kMimeTypeText)); - if (target_list.ContainsFormat(ClipboardFormatType::GetHtmlType())) - types->push_back(base::UTF8ToUTF16(kMimeTypeHTML)); - if (target_list.ContainsFormat(ClipboardFormatType::GetRtfType())) - types->push_back(base::UTF8ToUTF16(kMimeTypeRTF)); - if (target_list.ContainsFormat(ClipboardFormatType::GetBitmapType())) - types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); - // Only support filenames if chrome://flags#clipboard-filenames is enabled. - if (target_list.ContainsFormat(ClipboardFormatType::GetFilenamesType()) && - base::FeatureList::IsEnabled(features::kClipboardFilenames)) - types->push_back(base::UTF8ToUTF16(kMimeTypeURIList)); - - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, x11_details_->GetAtomsForFormat( - ClipboardFormatType::GetWebCustomDataType()))); - if (data.IsValid()) - ReadCustomDataTypes(data.GetData(), data.GetSize(), types); + auto available_types = x_clipboard_helper_->GetAvailableTypes(buffer); + for (const auto& mime_type : available_types) { + // Special handling for chromium/x-web-custom-data. We must read the data + // and deserialize it to find the list of mime types to report. + if (mime_type == ClipboardFormatType::GetWebCustomDataType().GetName()) { + auto data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( + ClipboardFormatType::GetWebCustomDataType()))); + if (data.IsValid()) + ReadCustomDataTypes(data.GetData(), data.GetSize(), types); + } else { + types->push_back(base::UTF8ToUTF16(mime_type)); + } + } } // |data_dst| is not used. It's only passed to be consistent with other // platforms. -std::vector +std::vector ClipboardX11::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const { DCHECK(CalledOnValidThread()); - - // Copy target_list(), so that XGetAtomNames can get a non-const Atom*. - TargetList::AtomVector target_list = - x11_details_->WaitAndGetTargetsList(buffer).target_list(); - if (target_list.empty()) - return {}; - - std::vector> futures; - for (x11::Atom target : target_list) - futures.push_back(x11::Connection::Get()->GetAtomName({target})); - std::vector types; - types.reserve(target_list.size()); - for (auto& future : futures) { - if (auto response = future.Sync()) - types.push_back(base::UTF8ToUTF16(response->name)); - else - types.emplace_back(); - } - - return types; + std::vector format_names; + for (const auto& name : x_clipboard_helper_->GetAvailableAtomNames(buffer)) + format_names.push_back(base::UTF8ToUTF16(name)); + return format_names; } // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardX11::ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kText); - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, x11_details_->GetTextAtoms())); + SelectionData data( + x_clipboard_helper_->Read(buffer, x_clipboard_helper_->GetTextAtoms())); if (data.IsValid()) { std::string text = data.GetText(); *result = base::UTF8ToUTF16(text); @@ -608,8 +136,8 @@ void ClipboardX11::ReadAsciiText(ClipboardBuffer buffer, DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kText); - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, x11_details_->GetTextAtoms())); + SelectionData data( + x_clipboard_helper_->Read(buffer, x_clipboard_helper_->GetTextAtoms())); if (data.IsValid()) result->assign(data.GetText()); } @@ -620,7 +148,7 @@ void ClipboardX11::ReadAsciiText(ClipboardBuffer buffer, // platforms. void ClipboardX11::ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const { @@ -632,9 +160,9 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer, *fragment_start = 0; *fragment_end = 0; - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, - x11_details_->GetAtomsForFormat(ClipboardFormatType::GetHtmlType()))); + SelectionData data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( + ClipboardFormatType::GetHtmlType()))); if (data.IsValid()) { *markup = data.GetHtml(); @@ -648,13 +176,13 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer, // platforms. void ClipboardX11::ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kSvg); - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, - x11_details_->GetAtomsForFormat(ClipboardFormatType::GetSvgType()))); + SelectionData data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( + ClipboardFormatType::GetSvgType()))); if (data.IsValid()) { std::string markup; data.AssignTo(&markup); @@ -670,9 +198,9 @@ void ClipboardX11::ReadRTF(ClipboardBuffer buffer, DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kRtf); - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, - x11_details_->GetAtomsForFormat(ClipboardFormatType::GetRtfType()))); + SelectionData data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( + ClipboardFormatType::GetRtfType()))); if (data.IsValid()) data.AssignTo(result); } @@ -690,14 +218,14 @@ void ClipboardX11::ReadImage(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardX11::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const { + std::u16string* result) const { DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kCustomData); - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, x11_details_->GetAtomsForFormat( + SelectionData data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( ClipboardFormatType::GetWebCustomDataType()))); if (data.IsValid()) ReadCustomDataForType(data.GetData(), data.GetSize(), type, result); @@ -711,8 +239,8 @@ void ClipboardX11::ReadFilenames(ClipboardBuffer buffer, DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kFilenames); - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, x11_details_->GetAtomsForFormat( + SelectionData data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( ClipboardFormatType::GetFilenamesType()))); std::string uri_list; if (data.IsValid()) @@ -723,7 +251,7 @@ void ClipboardX11::ReadFilenames(ClipboardBuffer buffer, // |data_dst| is not used. It's only passed to be consistent with other // platforms. void ClipboardX11::ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const { DCHECK(CalledOnValidThread()); // TODO(erg): This was left NOTIMPLEMENTED() in the gtk port too. @@ -738,8 +266,9 @@ void ClipboardX11::ReadData(const ClipboardFormatType& format, DCHECK(CalledOnValidThread()); RecordRead(ClipboardFormatMetric::kData); - SelectionData data(x11_details_->RequestAndWaitForTypes( - ClipboardBuffer::kCopyPaste, x11_details_->GetAtomsForFormat(format))); + SelectionData data(x_clipboard_helper_->Read( + ClipboardBuffer::kCopyPaste, + x_clipboard_helper_->GetAtomsForFormat(format))); if (data.IsValid()) data.AssignTo(result); } @@ -759,22 +288,23 @@ void ClipboardX11::WritePortableRepresentations( DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); - x11_details_->CreateNewClipboardData(); + x_clipboard_helper_->CreateNewClipboardData(); for (const auto& object : objects) DispatchPortableRepresentation(object.first, object.second); - x11_details_->TakeOwnershipOfSelection(buffer); + x_clipboard_helper_->TakeOwnershipOfSelection(buffer); if (buffer == ClipboardBuffer::kCopyPaste) { auto text_iter = objects.find(PortableFormat::kText); if (text_iter != objects.end()) { - x11_details_->CreateNewClipboardData(); + x_clipboard_helper_->CreateNewClipboardData(); const ObjectMapParams& params_vector = text_iter->second; if (params_vector.size()) { const ObjectMapParam& char_vector = params_vector[0]; if (char_vector.size()) WriteText(&char_vector.front(), char_vector.size()); } - x11_details_->TakeOwnershipOfSelection(ClipboardBuffer::kSelection); + x_clipboard_helper_->TakeOwnershipOfSelection( + ClipboardBuffer::kSelection); } } @@ -790,9 +320,9 @@ void ClipboardX11::WritePlatformRepresentations( DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); - x11_details_->CreateNewClipboardData(); + x_clipboard_helper_->CreateNewClipboardData(); DispatchPlatformRepresentations(std::move(platform_representations)); - x11_details_->TakeOwnershipOfSelection(buffer); + x_clipboard_helper_->TakeOwnershipOfSelection(buffer); data_src_[buffer] = std::move(data_src); } @@ -801,10 +331,10 @@ void ClipboardX11::WriteText(const char* text_data, size_t text_len) { scoped_refptr mem( base::RefCountedString::TakeString(&str)); - x11_details_->InsertMapping(kMimeTypeText, mem); - x11_details_->InsertMapping(kMimeTypeLinuxText, mem); - x11_details_->InsertMapping(kMimeTypeLinuxString, mem); - x11_details_->InsertMapping(kMimeTypeLinuxUtf8String, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeText, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeLinuxText, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeLinuxString, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeLinuxUtf8String, mem); } void ClipboardX11::WriteHTML(const char* markup_data, @@ -822,7 +352,7 @@ void ClipboardX11::WriteHTML(const char* markup_data, scoped_refptr mem( base::RefCountedString::TakeString(&data)); - x11_details_->InsertMapping(kMimeTypeHTML, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeHTML, mem); } void ClipboardX11::WriteSvg(const char* markup_data, size_t markup_len) { @@ -830,7 +360,7 @@ void ClipboardX11::WriteSvg(const char* markup_data, size_t markup_len) { scoped_refptr mem( base::RefCountedString::TakeString(&str)); - x11_details_->InsertMapping(kMimeTypeSvg, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeSvg, mem); } void ClipboardX11::WriteRTF(const char* rtf_data, size_t data_len) { @@ -841,8 +371,8 @@ void ClipboardX11::WriteFilenames(std::vector filenames) { std::string uri_list = ui::FileInfosToURIList(filenames); scoped_refptr mem( base::RefCountedString::TakeString(&uri_list)); - x11_details_->InsertMapping(ClipboardFormatType::GetFilenamesType().GetName(), - mem); + x_clipboard_helper_->InsertMapping( + ClipboardFormatType::GetFilenamesType().GetName(), mem); } void ClipboardX11::WriteBookmark(const char* title_data, @@ -850,8 +380,8 @@ void ClipboardX11::WriteBookmark(const char* title_data, const char* url_data, size_t url_len) { // Write as a mozilla url (UTF16: URL, newline, title). - base::string16 url = base::UTF8ToUTF16(std::string(url_data, url_len) + "\n"); - base::string16 title = + std::u16string url = base::UTF8ToUTF16(std::string(url_data, url_len) + "\n"); + std::u16string title = base::UTF8ToUTF16(base::StringPiece(title_data, title_len)); std::vector data; @@ -860,24 +390,25 @@ void ClipboardX11::WriteBookmark(const char* title_data, scoped_refptr mem( base::RefCountedBytes::TakeVector(&data)); - x11_details_->InsertMapping(kMimeTypeMozillaURL, mem); + x_clipboard_helper_->InsertMapping(kMimeTypeMozillaURL, mem); } // Write an extra flavor that signifies WebKit was the last to modify the // pasteboard. This flavor has no data. void ClipboardX11::WriteWebSmartPaste() { std::string empty; - x11_details_->InsertMapping(kMimeTypeWebkitSmartPaste, - scoped_refptr( - base::RefCountedString::TakeString(&empty))); + x_clipboard_helper_->InsertMapping( + kMimeTypeWebkitSmartPaste, + scoped_refptr( + base::RefCountedString::TakeString(&empty))); } void ClipboardX11::WriteBitmap(const SkBitmap& bitmap) { // Encode the bitmap as a PNG for transport. std::vector output; if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &output)) { - x11_details_->InsertMapping(kMimeTypePNG, - base::RefCountedBytes::TakeVector(&output)); + x_clipboard_helper_->InsertMapping( + kMimeTypePNG, base::RefCountedBytes::TakeVector(&output)); } } @@ -887,7 +418,7 @@ void ClipboardX11::WriteData(const ClipboardFormatType& format, std::vector bytes(data_data, data_data + data_len); scoped_refptr mem( base::RefCountedBytes::TakeVector(&bytes)); - x11_details_->InsertMapping(format.GetName(), mem); + x_clipboard_helper_->InsertMapping(format.GetName(), mem); } SkBitmap ClipboardX11::ReadImageInternal(ClipboardBuffer buffer) const { @@ -896,9 +427,9 @@ SkBitmap ClipboardX11::ReadImageInternal(ClipboardBuffer buffer) const { // TODO(https://crbug.com/443355): Since now that ReadImage() is async, // refactor the code to keep a callback with the request, and invoke the // callback when the request is satisfied. - SelectionData data(x11_details_->RequestAndWaitForTypes( - buffer, - x11_details_->GetAtomsForFormat(ClipboardFormatType::GetBitmapType()))); + SelectionData data(x_clipboard_helper_->Read( + buffer, x_clipboard_helper_->GetAtomsForFormat( + ClipboardFormatType::GetBitmapType()))); if (data.IsValid()) { SkBitmap bitmap; if (gfx::PNGCodec::Decode(data.GetData(), data.GetSize(), &bitmap)) @@ -908,4 +439,12 @@ SkBitmap ClipboardX11::ReadImageInternal(ClipboardBuffer buffer) const { return SkBitmap(); } +void ClipboardX11::OnSelectionChanged(ClipboardBuffer buffer) { + if (buffer == ClipboardBuffer::kCopyPaste) + clipboard_sequence_number_++; + else + primary_sequence_number_++; + ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged(); +} + } // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard_x11.h b/chromium/ui/base/clipboard/clipboard_x11.h index 05896354132..286c15e4560 100644 --- a/chromium/ui/base/clipboard/clipboard_x11.h +++ b/chromium/ui/base/clipboard/clipboard_x11.h @@ -5,16 +5,17 @@ #ifndef UI_BASE_CLIPBOARD_CLIPBOARD_X11_H_ #define UI_BASE_CLIPBOARD_CLIPBOARD_X11_H_ -#include -#include - +#include #include #include "base/macros.h" #include "ui/base/clipboard/clipboard.h" +#include "ui/base/clipboard/clipboard_buffer.h" namespace ui { +class XClipboardHelper; + class ClipboardX11 : public Clipboard { private: friend class Clipboard; @@ -32,25 +33,25 @@ class ClipboardX11 : public Clipboard { void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - std::vector* types) const override; - std::vector ReadAvailablePlatformSpecificFormatNames( + std::vector* types) const override; + std::vector ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer, const DataTransferEndpoint* data_dst) const override; void ReadText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadAsciiText(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; void ReadHTML(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* markup, + std::u16string* markup, std::string* src_url, uint32_t* fragment_start, uint32_t* fragment_end) const override; void ReadSvg(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadRTF(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::string* result) const override; @@ -58,14 +59,14 @@ class ClipboardX11 : public Clipboard { const DataTransferEndpoint* data_dst, ReadImageCallback callback) const override; void ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, + const std::u16string& type, const DataTransferEndpoint* data_dst, - base::string16* result) const override; + std::u16string* result) const override; void ReadFilenames(ClipboardBuffer buffer, const DataTransferEndpoint* data_dst, std::vector* result) const override; void ReadBookmark(const DataTransferEndpoint* data_dst, - base::string16* title, + std::u16string* title, std::string* url) const override; void ReadData(const ClipboardFormatType& format, const DataTransferEndpoint* data_dst, @@ -100,11 +101,13 @@ class ClipboardX11 : public Clipboard { size_t data_len) override; SkBitmap ReadImageInternal(ClipboardBuffer buffer) const; + void OnSelectionChanged(ClipboardBuffer buffer); + + std::unique_ptr x_clipboard_helper_; + + uint64_t clipboard_sequence_number_ = 0; + uint64_t primary_sequence_number_ = 0; - // TODO(dcheng): Is this still needed now that each platform clipboard has its - // own class derived from Clipboard? - class X11Details; - std::unique_ptr x11_details_; base::flat_map> data_src_; diff --git a/chromium/ui/base/clipboard/custom_data_helper.cc b/chromium/ui/base/clipboard/custom_data_helper.cc index 4cc5b295340..96bd53b0172 100644 --- a/chromium/ui/base/clipboard/custom_data_helper.cc +++ b/chromium/ui/base/clipboard/custom_data_helper.cc @@ -4,7 +4,7 @@ // // TODO(dcheng): For efficiency reasons, consider passing custom data around // as a vector instead. It allows us to append a -// std::pair and swap the deserialized values. +// std::pair and swap the deserialized values. #include "ui/base/clipboard/custom_data_helper.h" @@ -22,14 +22,14 @@ bool SkipString16(base::PickleIterator* iter) { int len; if (!iter->ReadLength(&len)) return false; - return iter->SkipBytes(len * sizeof(base::char16)); + return iter->SkipBytes(len * sizeof(char16_t)); } } // namespace void ReadCustomDataTypes(const void* data, size_t data_length, - std::vector* types) { + std::vector* types) { base::Pickle pickle(reinterpret_cast(data), data_length); base::PickleIterator iter(pickle); @@ -43,7 +43,7 @@ void ReadCustomDataTypes(const void* data, size_t original_size = types->size(); for (uint32_t i = 0; i < size; ++i) { - types->push_back(base::string16()); + types->push_back(std::u16string()); if (!iter.ReadString16(&types->back()) || !SkipString16(&iter)) { types->resize(original_size); return; @@ -53,8 +53,8 @@ void ReadCustomDataTypes(const void* data, void ReadCustomDataForType(const void* data, size_t data_length, - const base::string16& type, - base::string16* result) { + const std::u16string& type, + std::u16string* result) { base::Pickle pickle(reinterpret_cast(data), data_length); base::PickleIterator iter(pickle); @@ -63,7 +63,7 @@ void ReadCustomDataForType(const void* data, return; for (uint32_t i = 0; i < size; ++i) { - base::string16 deserialized_type; + std::u16string deserialized_type; if (!iter.ReadString16(&deserialized_type)) return; if (deserialized_type == type) { @@ -78,7 +78,7 @@ void ReadCustomDataForType(const void* data, void ReadCustomDataIntoMap( const void* data, size_t data_length, - std::unordered_map* result) { + std::unordered_map* result) { base::Pickle pickle(reinterpret_cast(data), data_length); base::PickleIterator iter(pickle); @@ -87,13 +87,13 @@ void ReadCustomDataIntoMap( return; for (uint32_t i = 0; i < size; ++i) { - base::string16 type; + std::u16string type; if (!iter.ReadString16(&type)) { // Data is corrupt, return an empty map. result->clear(); return; } - auto insert_result = result->insert({type, base::string16()}); + auto insert_result = result->insert({type, std::u16string()}); if (!iter.ReadString16(&insert_result.first->second)) { // Data is corrupt, return an empty map. result->clear(); @@ -103,7 +103,7 @@ void ReadCustomDataIntoMap( } void WriteCustomDataToPickle( - const std::unordered_map& data, + const std::unordered_map& data, base::Pickle* pickle) { pickle->WriteUInt32(data.size()); for (const auto& it : data) { @@ -113,7 +113,7 @@ void WriteCustomDataToPickle( } void WriteCustomDataToPickle( - const base::flat_map& data, + const base::flat_map& data, base::Pickle* pickle) { pickle->WriteUInt32(data.size()); for (const auto& it : data) { diff --git a/chromium/ui/base/clipboard/custom_data_helper.h b/chromium/ui/base/clipboard/custom_data_helper.h index f4537272fdd..c2fc581234e 100644 --- a/chromium/ui/base/clipboard/custom_data_helper.h +++ b/chromium/ui/base/clipboard/custom_data_helper.h @@ -7,12 +7,12 @@ #include +#include #include #include #include "base/component_export.h" #include "base/containers/flat_map.h" -#include "base/strings/string16.h" #include "build/build_config.h" // Due to restrictions of most operating systems, we don't directly map each @@ -28,26 +28,26 @@ namespace ui { COMPONENT_EXPORT(UI_BASE_CLIPBOARD) void ReadCustomDataTypes(const void* data, size_t data_length, - std::vector* types); + std::vector* types); COMPONENT_EXPORT(UI_BASE_CLIPBOARD) void ReadCustomDataForType(const void* data, size_t data_length, - const base::string16& type, - base::string16* result); + const std::u16string& type, + std::u16string* result); COMPONENT_EXPORT(UI_BASE_CLIPBOARD) void ReadCustomDataIntoMap( const void* data, size_t data_length, - std::unordered_map* result); + std::unordered_map* result); COMPONENT_EXPORT(UI_BASE_CLIPBOARD) void WriteCustomDataToPickle( - const std::unordered_map& data, + const std::unordered_map& data, base::Pickle* pickle); COMPONENT_EXPORT(UI_BASE_CLIPBOARD) void WriteCustomDataToPickle( - const base::flat_map& data, + const base::flat_map& data, base::Pickle* pickle); } // namespace ui diff --git a/chromium/ui/base/clipboard/custom_data_helper_unittest.cc b/chromium/ui/base/clipboard/custom_data_helper_unittest.cc index 8045eff334c..e411b1187e1 100644 --- a/chromium/ui/base/clipboard/custom_data_helper_unittest.cc +++ b/chromium/ui/base/clipboard/custom_data_helper_unittest.cc @@ -17,15 +17,13 @@ namespace ui { namespace { void PrepareEmptyTestData(base::Pickle* pickle) { - std::unordered_map data; + std::unordered_map data; WriteCustomDataToPickle(data, pickle); } void PrepareTestData(base::Pickle* pickle) { - std::unordered_map data = { - {ASCIIToUTF16("abc"), base::string16()}, - {ASCIIToUTF16("de"), ASCIIToUTF16("1")}, - {ASCIIToUTF16("f"), ASCIIToUTF16("23")}}; + std::unordered_map data = { + {u"abc", std::u16string()}, {u"de", u"1"}, {u"f", u"23"}}; WriteCustomDataToPickle(data, pickle); } @@ -33,7 +31,7 @@ TEST(CustomDataHelperTest, EmptyReadTypes) { base::Pickle pickle; PrepareEmptyTestData(&pickle); - std::vector types; + std::vector types; ReadCustomDataTypes(pickle.data(), pickle.size(), &types); EXPECT_EQ(0u, types.size()); } @@ -42,19 +40,16 @@ TEST(CustomDataHelperTest, EmptyReadSingleType) { base::Pickle pickle; PrepareEmptyTestData(&pickle); - base::string16 result; - ReadCustomDataForType(pickle.data(), - pickle.size(), - ASCIIToUTF16("f"), - &result); - EXPECT_EQ(base::string16(), result); + std::u16string result; + ReadCustomDataForType(pickle.data(), pickle.size(), u"f", &result); + EXPECT_EQ(std::u16string(), result); } TEST(CustomDataHelperTest, EmptyReadMap) { base::Pickle pickle; PrepareEmptyTestData(&pickle); - std::unordered_map result; + std::unordered_map result; ReadCustomDataIntoMap(pickle.data(), pickle.size(), &result); EXPECT_EQ(0u, result.size()); } @@ -63,11 +58,10 @@ TEST(CustomDataHelperTest, ReadTypes) { base::Pickle pickle; PrepareTestData(&pickle); - std::vector types; + std::vector types; ReadCustomDataTypes(pickle.data(), pickle.size(), &types); - std::vector expected = { - ASCIIToUTF16("abc"), ASCIIToUTF16("de"), ASCIIToUTF16("f")}; + std::vector expected = {u"abc", u"de", u"f"}; // We need to sort to compare equality, as the underlying custom data is // unordered std::sort(types.begin(), types.end()); @@ -79,86 +73,69 @@ TEST(CustomDataHelperTest, ReadSingleType) { base::Pickle pickle; PrepareTestData(&pickle); - base::string16 result; - ReadCustomDataForType(pickle.data(), - pickle.size(), - ASCIIToUTF16("abc"), - &result); - EXPECT_EQ(base::string16(), result); - - ReadCustomDataForType(pickle.data(), - pickle.size(), - ASCIIToUTF16("de"), - &result); - EXPECT_EQ(ASCIIToUTF16("1"), result); - - ReadCustomDataForType(pickle.data(), - pickle.size(), - ASCIIToUTF16("f"), - &result); - EXPECT_EQ(ASCIIToUTF16("23"), result); + std::u16string result; + ReadCustomDataForType(pickle.data(), pickle.size(), u"abc", &result); + EXPECT_EQ(std::u16string(), result); + + ReadCustomDataForType(pickle.data(), pickle.size(), u"de", &result); + EXPECT_EQ(u"1", result); + + ReadCustomDataForType(pickle.data(), pickle.size(), u"f", &result); + EXPECT_EQ(u"23", result); } TEST(CustomDataHelperTest, ReadMap) { base::Pickle pickle; PrepareTestData(&pickle); - std::unordered_map result; + std::unordered_map result; ReadCustomDataIntoMap(pickle.data(), pickle.size(), &result); - std::unordered_map expected = { - {ASCIIToUTF16("abc"), base::string16()}, - {ASCIIToUTF16("de"), ASCIIToUTF16("1")}, - {ASCIIToUTF16("f"), ASCIIToUTF16("23")}}; + std::unordered_map expected = { + {u"abc", std::u16string()}, {u"de", u"1"}, {u"f", u"23"}}; EXPECT_EQ(expected, result); } TEST(CustomDataHelperTest, BadReadTypes) { // ReadCustomDataTypes makes the additional guarantee that the contents of the // result vector will not change if the input is malformed. - std::vector expected = { - ASCIIToUTF16("abc"), ASCIIToUTF16("de"), ASCIIToUTF16("f")}; + std::vector expected = {u"abc", u"de", u"f"}; base::Pickle malformed; malformed.WriteUInt32(1000); - malformed.WriteString16(ASCIIToUTF16("hello")); - malformed.WriteString16(ASCIIToUTF16("world")); - std::vector actual(expected); + malformed.WriteString16(u"hello"); + malformed.WriteString16(u"world"); + std::vector actual(expected); ReadCustomDataTypes(malformed.data(), malformed.size(), &actual); EXPECT_EQ(expected, actual); base::Pickle malformed2; malformed2.WriteUInt32(1); - malformed2.WriteString16(ASCIIToUTF16("hello")); - std::vector actual2(expected); + malformed2.WriteString16(u"hello"); + std::vector actual2(expected); ReadCustomDataTypes(malformed2.data(), malformed2.size(), &actual2); EXPECT_EQ(expected, actual2); } TEST(CustomDataHelperTest, BadPickle) { - base::string16 result_data; - std::unordered_map result_map; + std::u16string result_data; + std::unordered_map result_map; base::Pickle malformed; malformed.WriteUInt32(1000); - malformed.WriteString16(ASCIIToUTF16("hello")); - malformed.WriteString16(ASCIIToUTF16("world")); + malformed.WriteString16(u"hello"); + malformed.WriteString16(u"world"); - ReadCustomDataForType(malformed.data(), - malformed.size(), - ASCIIToUTF16("f"), - &result_data); + ReadCustomDataForType(malformed.data(), malformed.size(), u"f", &result_data); ReadCustomDataIntoMap(malformed.data(), malformed.size(), &result_map); EXPECT_EQ(0u, result_data.size()); EXPECT_EQ(0u, result_map.size()); base::Pickle malformed2; malformed2.WriteUInt32(1); - malformed2.WriteString16(ASCIIToUTF16("hello")); + malformed2.WriteString16(u"hello"); - ReadCustomDataForType(malformed2.data(), - malformed2.size(), - ASCIIToUTF16("f"), + ReadCustomDataForType(malformed2.data(), malformed2.size(), u"f", &result_data); ReadCustomDataIntoMap(malformed2.data(), malformed2.size(), &result_map); EXPECT_EQ(0u, result_data.size()); diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.cc b/chromium/ui/base/clipboard/scoped_clipboard_writer.cc index 852462421f8..4e2394e4116 100644 --- a/chromium/ui/base/clipboard/scoped_clipboard_writer.cc +++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.cc @@ -40,7 +40,7 @@ ScopedClipboardWriter::~ScopedClipboardWriter() { Clipboard::GetForCurrentThread()->MarkAsConfidential(); } -void ScopedClipboardWriter::WriteText(const base::string16& text) { +void ScopedClipboardWriter::WriteText(const std::u16string& text) { RecordWrite(ClipboardFormatMetric::kText); std::string utf8_text = base::UTF16ToUTF8(text); @@ -50,7 +50,7 @@ void ScopedClipboardWriter::WriteText(const base::string16& text) { objects_[Clipboard::PortableFormat::kText] = parameters; } -void ScopedClipboardWriter::WriteHTML(const base::string16& markup, +void ScopedClipboardWriter::WriteHTML(const std::u16string& markup, const std::string& source_url) { RecordWrite(ClipboardFormatMetric::kHtml); std::string utf8_markup = base::UTF16ToUTF8(markup); @@ -67,7 +67,7 @@ void ScopedClipboardWriter::WriteHTML(const base::string16& markup, objects_[Clipboard::PortableFormat::kHtml] = parameters; } -void ScopedClipboardWriter::WriteSvg(const base::string16& markup) { +void ScopedClipboardWriter::WriteSvg(const std::u16string& markup) { RecordWrite(ClipboardFormatMetric::kSvg); std::string utf8_markup = base::UTF16ToUTF8(markup); @@ -93,7 +93,7 @@ void ScopedClipboardWriter::WriteFilenames(const std::string& uri_list) { objects_[Clipboard::PortableFormat::kFilenames] = parameters; } -void ScopedClipboardWriter::WriteBookmark(const base::string16& bookmark_title, +void ScopedClipboardWriter::WriteBookmark(const std::u16string& bookmark_title, const std::string& url) { if (bookmark_title.empty() || url.empty()) return; @@ -108,7 +108,7 @@ void ScopedClipboardWriter::WriteBookmark(const base::string16& bookmark_title, objects_[Clipboard::PortableFormat::kBookmark] = parameters; } -void ScopedClipboardWriter::WriteHyperlink(const base::string16& anchor_text, +void ScopedClipboardWriter::WriteHyperlink(const std::u16string& anchor_text, const std::string& url) { if (anchor_text.empty() || url.empty()) return; @@ -173,7 +173,7 @@ void ScopedClipboardWriter::WritePickledData( objects_[Clipboard::PortableFormat::kData] = parameters; } -void ScopedClipboardWriter::WriteData(const base::string16& format, +void ScopedClipboardWriter::WriteData(const std::u16string& format, mojo_base::BigBuffer data) { RecordWrite(ClipboardFormatMetric::kData); platform_representations_.push_back( diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.h b/chromium/ui/base/clipboard/scoped_clipboard_writer.h index 5e6ccf7afd0..dfe6fbab6bf 100644 --- a/chromium/ui/base/clipboard/scoped_clipboard_writer.h +++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.h @@ -9,7 +9,6 @@ #include "base/component_export.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" @@ -41,14 +40,14 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter { ~ScopedClipboardWriter(); // Converts |text| to UTF-8 and adds it to the clipboard. - void WriteText(const base::string16& text); + void WriteText(const std::u16string& text); // Adds HTML to the clipboard. The url parameter is optional, but especially // useful if the HTML fragment contains relative links. - void WriteHTML(const base::string16& markup, const std::string& source_url); + void WriteHTML(const std::u16string& markup, const std::string& source_url); // Adds SVG to the clipboard. - void WriteSvg(const base::string16& text); + void WriteSvg(const std::u16string& text); // Adds RTF to the clipboard. void WriteRTF(const std::string& rtf_data); @@ -60,12 +59,12 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter { void WriteFilenames(const std::string& uri_list); // Adds a bookmark to the clipboard. - void WriteBookmark(const base::string16& bookmark_title, + void WriteBookmark(const std::u16string& bookmark_title, const std::string& url); // Adds an html hyperlink () to the clipboard. |anchor_text| and // |url| will be escaped as needed. - void WriteHyperlink(const base::string16& anchor_text, + void WriteHyperlink(const std::u16string& anchor_text, const std::string& url); // Used by WebKit to determine whether WebKit wrote the clipboard last @@ -77,7 +76,7 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter { // Data is written to the system clipboard in the same order as WriteData // calls are received. - void WriteData(const base::string16& format, mojo_base::BigBuffer data); + void WriteData(const std::u16string& format, mojo_base::BigBuffer data); void WriteImage(const SkBitmap& bitmap); diff --git a/chromium/ui/base/cocoa/command_dispatcher.h b/chromium/ui/base/cocoa/command_dispatcher.h index c2e437dcb68..ca79f3d2382 100644 --- a/chromium/ui/base/cocoa/command_dispatcher.h +++ b/chromium/ui/base/cocoa/command_dispatcher.h @@ -16,11 +16,11 @@ // CommandDispatcher guides the processing of key events to ensure key commands // are executed in the appropriate order. In particular, it allows a first -// responder implementing CommandDispatcherTarget to handle an event -// asynchronously and return unhandled events via -redispatchKeyEvent:. An -// NSWindow can use CommandDispatcher by implementing CommandDispatchingWindow -// and overriding -[NSWindow performKeyEquivalent:] and -[NSWindow sendEvent:] -// to call the respective CommandDispatcher methods. +// responder to handle an event asynchronously and return unhandled events +// via -redispatchKeyEvent:. An NSWindow can use CommandDispatcher by +// implementing CommandDispatchingWindow and overriding +// -[NSWindow performKeyEquivalent:] and -[NSWindow sendEvent:] to call the +// respective CommandDispatcher methods. COMPONENT_EXPORT(UI_BASE) @interface CommandDispatcher : NSObject diff --git a/chromium/ui/base/cocoa/command_dispatcher.mm b/chromium/ui/base/cocoa/command_dispatcher.mm index c905b6be5a5..dbc19a6c1f7 100644 --- a/chromium/ui/base/cocoa/command_dispatcher.mm +++ b/chromium/ui/base/cocoa/command_dispatcher.mm @@ -175,7 +175,7 @@ NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { id appController = [NSApp delegate]; DCHECK([appController - conformsToProtocol:@protocol(NSUserInterfaceValidations)]); + respondsToSelector:@selector(validateUserInterfaceItem:)]); if ([appController validateUserInterfaceItem:item]) return YES; } diff --git a/chromium/ui/base/cocoa/find_pasteboard.h b/chromium/ui/base/cocoa/find_pasteboard.h index 3dc0867ca8e..af199b052f5 100644 --- a/chromium/ui/base/cocoa/find_pasteboard.h +++ b/chromium/ui/base/cocoa/find_pasteboard.h @@ -5,7 +5,8 @@ #ifndef UI_BASE_COCOA_FIND_PASTEBOARD_H_ #define UI_BASE_COCOA_FIND_PASTEBOARD_H_ -#include "base/strings/string16.h" +#include + #ifdef __OBJC__ @@ -54,6 +55,6 @@ COMPONENT_EXPORT(UI_BASE) #endif // __OBJC__ // Also provide a c++ interface -COMPONENT_EXPORT(UI_BASE) base::string16 GetFindPboardText(); +COMPONENT_EXPORT(UI_BASE) std::u16string GetFindPboardText(); #endif // UI_BASE_COCOA_FIND_PASTEBOARD_H_ diff --git a/chromium/ui/base/cocoa/find_pasteboard.mm b/chromium/ui/base/cocoa/find_pasteboard.mm index 0968d213f09..4850338e95c 100644 --- a/chromium/ui/base/cocoa/find_pasteboard.mm +++ b/chromium/ui/base/cocoa/find_pasteboard.mm @@ -76,6 +76,6 @@ NSString* kFindPasteboardChangedNotification = @end -base::string16 GetFindPboardText() { +std::u16string GetFindPboardText() { return base::SysNSStringToUTF16([[FindPasteboard sharedInstance] findText]); } diff --git a/chromium/ui/base/cocoa/menu_controller.h b/chromium/ui/base/cocoa/menu_controller.h index 566dc965045..ace28e03577 100644 --- a/chromium/ui/base/cocoa/menu_controller.h +++ b/chromium/ui/base/cocoa/menu_controller.h @@ -7,9 +7,10 @@ #import +#include + #include "base/component_export.h" #include "base/mac/scoped_nsobject.h" -#include "base/strings/string16.h" namespace ui { class MenuModel; diff --git a/chromium/ui/base/cocoa/menu_controller_unittest.mm b/chromium/ui/base/cocoa/menu_controller_unittest.mm index 549e3abc18a..71496c0eef2 100644 --- a/chromium/ui/base/cocoa/menu_controller_unittest.mm +++ b/chromium/ui/base/cocoa/menu_controller_unittest.mm @@ -63,7 +63,7 @@ class TestSimpleMenuModelVisibility : public SimpleMenuModel { items_[ValidateItemIndex(index)].visible = visible; } - void AddItem(int command_id, const base::string16& label) { + void AddItem(int command_id, const std::u16string& label) { SimpleMenuModel::AddItem(command_id, label); items_.push_back({true, command_id}); } @@ -146,18 +146,18 @@ class DynamicDelegate : public Delegate { public: DynamicDelegate() {} bool IsItemForCommandIdDynamic(int command_id) const override { return true; } - base::string16 GetLabelForCommandId(int command_id) const override { + std::u16string GetLabelForCommandId(int command_id) const override { return label_; } ui::ImageModel GetIconForCommandId(int command_id) const override { return icon_.IsEmpty() ? ui::ImageModel() : ui::ImageModel::FromImage(icon_); } - void SetDynamicLabel(base::string16 label) { label_ = label; } + void SetDynamicLabel(std::u16string label) { label_ = label; } void SetDynamicIcon(const gfx::Image& icon) { icon_ = icon; } private: - base::string16 label_; + std::u16string label_; gfx::Image icon_; }; @@ -167,7 +167,7 @@ class OwningDelegate : public Delegate { public: OwningDelegate(bool* did_delete, BOOL* did_dealloc) : did_delete_(did_delete), model_(this) { - model_.AddItem(1, ASCIIToUTF16("foo")); + model_.AddItem(1, u"foo"); controller_.reset([[WatchedLifetimeMenuController alloc] initWithModel:&model_ delegate:nil @@ -234,12 +234,12 @@ TEST_F(MenuControllerTest, EmptyMenu) { TEST_F(MenuControllerTest, BasicCreation) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); - model.AddItem(2, ASCIIToUTF16("two")); - model.AddItem(3, ASCIIToUTF16("three")); + model.AddItem(1, u"one"); + model.AddItem(2, u"two"); + model.AddItem(3, u"three"); model.AddSeparator(NORMAL_SEPARATOR); - model.AddItem(4, ASCIIToUTF16("four")); - model.AddItem(5, ASCIIToUTF16("five")); + model.AddItem(4, u"four"); + model.AddItem(5, u"five"); base::scoped_nsobject menu([[MenuControllerCocoa alloc] initWithModel:&model @@ -251,7 +251,7 @@ TEST_F(MenuControllerTest, BasicCreation) { // element. NSMenuItem* itemTwo = [[menu menu] itemAtIndex:2]; NSString* title = [itemTwo title]; - EXPECT_EQ(ASCIIToUTF16("three"), base::SysNSStringToUTF16(title)); + EXPECT_EQ(u"three", base::SysNSStringToUTF16(title)); EXPECT_EQ(2, [itemTwo tag]); EXPECT_TRUE([[[menu menu] itemAtIndex:3] isSeparatorItem]); @@ -260,13 +260,13 @@ TEST_F(MenuControllerTest, BasicCreation) { TEST_F(MenuControllerTest, Submenus) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); + model.AddItem(1, u"one"); SimpleMenuModel submodel(&delegate); - submodel.AddItem(2, ASCIIToUTF16("sub-one")); - submodel.AddItem(3, ASCIIToUTF16("sub-two")); - submodel.AddItem(4, ASCIIToUTF16("sub-three")); + submodel.AddItem(2, u"sub-one"); + submodel.AddItem(3, u"sub-two"); + submodel.AddItem(4, u"sub-three"); model.AddSubMenuWithStringId(5, kTestLabelResourceId, &submodel); - model.AddItem(6, ASCIIToUTF16("three")); + model.AddItem(6, u"three"); base::scoped_nsobject menu([[MenuControllerCocoa alloc] initWithModel:&model @@ -285,21 +285,21 @@ TEST_F(MenuControllerTest, Submenus) { // represented object and the proper tag. NSMenuItem* submenuItem = [submenu itemAtIndex:1]; NSString* title = [submenuItem title]; - EXPECT_EQ(ASCIIToUTF16("sub-two"), base::SysNSStringToUTF16(title)); + EXPECT_EQ(u"sub-two", base::SysNSStringToUTF16(title)); EXPECT_EQ(1, [submenuItem tag]); // Make sure the item after the submenu is correct and its represented // object is back to the top model. NSMenuItem* item = [[menu menu] itemAtIndex:2]; title = [item title]; - EXPECT_EQ(ASCIIToUTF16("three"), base::SysNSStringToUTF16(title)); + EXPECT_EQ(u"three", base::SysNSStringToUTF16(title)); EXPECT_EQ(2, [item tag]); } TEST_F(MenuControllerTest, EmptySubmenu) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); + model.AddItem(1, u"one"); SimpleMenuModel submodel(&delegate); model.AddSubMenuWithStringId(2, kTestLabelResourceId, &submodel); @@ -322,12 +322,12 @@ TEST_F(MenuControllerTest, EmptySubmenu) { TEST_F(MenuControllerTest, EmptySubmenuWhenAllChildItemsAreHidden) { Delegate delegate; TestSimpleMenuModelVisibility model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); + model.AddItem(1, u"one"); TestSimpleMenuModelVisibility submodel(&delegate); // Hide the two child menu items. - submodel.AddItem(2, ASCIIToUTF16("sub-one")); + submodel.AddItem(2, u"sub-one"); submodel.SetVisibility(2, false); - submodel.AddItem(3, ASCIIToUTF16("sub-two")); + submodel.AddItem(3, u"sub-two"); submodel.SetVisibility(3, false); model.AddSubMenuWithStringId(4, kTestLabelResourceId, &submodel); @@ -355,10 +355,10 @@ TEST_F(MenuControllerTest, HiddenSubmenu) { // Create the model. Delegate delegate; TestSimpleMenuModelVisibility model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); + model.AddItem(1, u"one"); TestSimpleMenuModelVisibility submodel(&delegate); - submodel.AddItem(2, ASCIIToUTF16("sub-one")); - submodel.AddItem(3, ASCIIToUTF16("sub-two")); + submodel.AddItem(2, u"sub-one"); + submodel.AddItem(3, u"sub-two"); // Set the submenu to be hidden. model.AddSubMenuWithStringId(4, kTestLabelResourceId, &submodel); @@ -403,12 +403,12 @@ TEST_F(MenuControllerTest, DisabledSubmenu) { // Create the model. Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); + model.AddItem(1, u"one"); SimpleMenuModel disabled_submodel(&delegate); - disabled_submodel.AddItem(2, ASCIIToUTF16("disabled_submodel")); + disabled_submodel.AddItem(2, u"disabled_submodel"); model.AddSubMenuWithStringId(3, kTestLabelResourceId, &disabled_submodel); SimpleMenuModel enabled_submodel(&delegate); - enabled_submodel.AddItem(4, ASCIIToUTF16("enabled_submodel")); + enabled_submodel.AddItem(4, u"enabled_submodel"); model.AddSubMenuWithStringId(5, kTestLabelResourceId, &enabled_submodel); // Disable the first submenu entry. @@ -450,9 +450,9 @@ TEST_F(MenuControllerTest, DisabledSubmenu) { TEST_F(MenuControllerTest, PopUpButton) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); - model.AddItem(2, ASCIIToUTF16("two")); - model.AddItem(3, ASCIIToUTF16("three")); + model.AddItem(1, u"one"); + model.AddItem(2, u"two"); + model.AddItem(3, u"three"); // Menu should have an extra item inserted at position 0 that has an empty // title. @@ -461,7 +461,7 @@ TEST_F(MenuControllerTest, PopUpButton) { delegate:nil useWithPopUpButtonCell:YES]); EXPECT_EQ(4, [[menu menu] numberOfItems]); - EXPECT_EQ(base::string16(), + EXPECT_EQ(std::u16string(), base::SysNSStringToUTF16([[[menu menu] itemAtIndex:0] title])); // Make sure the tags are still correct (the index no longer matches the tag). @@ -472,7 +472,7 @@ TEST_F(MenuControllerTest, PopUpButton) { TEST_F(MenuControllerTest, Execute) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); + model.AddItem(1, u"one"); base::scoped_nsobject menu([[MenuControllerCocoa alloc] initWithModel:&model delegate:nil @@ -498,10 +498,10 @@ void Validate(MenuControllerCocoa* controller, NSMenu* menu) { TEST_F(MenuControllerTest, Validate) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); - model.AddItem(2, ASCIIToUTF16("two")); + model.AddItem(1, u"one"); + model.AddItem(2, u"two"); SimpleMenuModel submodel(&delegate); - submodel.AddItem(2, ASCIIToUTF16("sub-one")); + submodel.AddItem(2, u"sub-one"); model.AddSubMenuWithStringId(3, kTestLabelResourceId, &submodel); base::scoped_nsobject menu([[MenuControllerCocoa alloc] @@ -521,8 +521,8 @@ TEST_F(MenuControllerTest, LabelFontList) { ui::ResourceBundle::FontDetails(std::string(), 0, gfx::Font::Weight::BOLD)); FontListMenuModel model(&delegate, &bold, 0); - model.AddItem(1, ASCIIToUTF16("one")); - model.AddItem(2, ASCIIToUTF16("two")); + model.AddItem(1, u"one"); + model.AddItem(2, u"two"); base::scoped_nsobject menu([[MenuControllerCocoa alloc] initWithModel:&model @@ -539,9 +539,9 @@ TEST_F(MenuControllerTest, LabelFontList) { TEST_F(MenuControllerTest, DefaultInitializer) { Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("one")); - model.AddItem(2, ASCIIToUTF16("two")); - model.AddItem(3, ASCIIToUTF16("three")); + model.AddItem(1, u"one"); + model.AddItem(2, u"two"); + model.AddItem(3, u"three"); base::scoped_nsobject menu( [[MenuControllerCocoa alloc] init]); @@ -553,7 +553,7 @@ TEST_F(MenuControllerTest, DefaultInitializer) { EXPECT_EQ(3, [[menu menu] numberOfItems]); // Check immutability. - model.AddItem(4, ASCIIToUTF16("four")); + model.AddItem(4, u"four"); EXPECT_EQ(3, [[menu menu] numberOfItems]); } @@ -563,10 +563,10 @@ TEST_F(MenuControllerTest, Dynamic) { // Create a menu containing a single item whose label is "initial" and who has // no icon. - base::string16 initial = ASCIIToUTF16("initial"); + std::u16string initial = u"initial"; delegate.SetDynamicLabel(initial); SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("foo")); + model.AddItem(1, u"foo"); base::scoped_nsobject menu([[MenuControllerCocoa alloc] initWithModel:&model delegate:nil @@ -581,7 +581,7 @@ TEST_F(MenuControllerTest, Dynamic) { EXPECT_EQ(nil, [item image]); // Now update the item to have a label of "second" and an icon. - base::string16 second = ASCIIToUTF16("second"); + std::u16string second = u"second"; delegate.SetDynamicLabel(second); const gfx::Image& icon = gfx::test::CreateImage(32, 32); delegate.SetDynamicIcon(icon); @@ -605,9 +605,9 @@ TEST_F(MenuControllerTest, OpenClose) { // Create the model. Delegate delegate; SimpleMenuModel model(&delegate); - model.AddItem(1, ASCIIToUTF16("allays")); - model.AddItem(2, ASCIIToUTF16("i")); - model.AddItem(3, ASCIIToUTF16("bf")); + model.AddItem(1, u"allays"); + model.AddItem(2, u"i"); + model.AddItem(3, u"bf"); // Create the controller. base::scoped_nsobject menu([[MenuControllerCocoa alloc] diff --git a/chromium/ui/base/cocoa/text_services_context_menu.cc b/chromium/ui/base/cocoa/text_services_context_menu.cc index 0dcfe6db2b4..b4f4d5101fc 100644 --- a/chromium/ui/base/cocoa/text_services_context_menu.cc +++ b/chromium/ui/base/cocoa/text_services_context_menu.cc @@ -60,7 +60,7 @@ TextServicesContextMenu::TextServicesContextMenu(Delegate* delegate) kWritingDirectionRtl, IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL); } -void TextServicesContextMenu::SpeakText(const base::string16& text) { +void TextServicesContextMenu::SpeakText(const std::u16string& text) { if (IsSpeaking()) StopSpeaking(); diff --git a/chromium/ui/base/cocoa/text_services_context_menu.h b/chromium/ui/base/cocoa/text_services_context_menu.h index a32b76f9523..4a95d5a59d1 100644 --- a/chromium/ui/base/cocoa/text_services_context_menu.h +++ b/chromium/ui/base/cocoa/text_services_context_menu.h @@ -5,10 +5,11 @@ #ifndef UI_BASE_COCOA_TEXT_SERVICES_CONTEXT_MENU_H_ #define UI_BASE_COCOA_TEXT_SERVICES_CONTEXT_MENU_H_ +#include + #include "base/component_export.h" #include "base/i18n/rtl.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/base/models/simple_menu_model.h" namespace ui { @@ -37,7 +38,7 @@ class COMPONENT_EXPORT(UI_BASE) TextServicesContextMenu class COMPONENT_EXPORT(UI_BASE) Delegate { public: // Returns the selected text. - virtual base::string16 GetSelectedText() const = 0; + virtual std::u16string GetSelectedText() const = 0; // Returns true if |direction| should be enabled in the BiDi submenu. virtual bool IsTextDirectionEnabled( @@ -54,7 +55,7 @@ class COMPONENT_EXPORT(UI_BASE) TextServicesContextMenu explicit TextServicesContextMenu(Delegate* delegate); // Methods for speaking. - static void SpeakText(const base::string16& text); + static void SpeakText(const std::u16string& text); static void StopSpeaking(); static bool IsSpeaking(); diff --git a/chromium/ui/base/cursor/cursor_factory.cc b/chromium/ui/base/cursor/cursor_factory.cc index 65afecadbb6..3d757428531 100644 --- a/chromium/ui/base/cursor/cursor_factory.cc +++ b/chromium/ui/base/cursor/cursor_factory.cc @@ -34,10 +34,9 @@ CursorFactory* CursorFactory::GetInstance() { return g_instance; } -base::Optional CursorFactory::GetDefaultCursor( - mojom::CursorType type) { +PlatformCursor CursorFactory::GetDefaultCursor(mojom::CursorType type) { NOTIMPLEMENTED(); - return base::nullopt; + return nullptr; } PlatformCursor CursorFactory::CreateImageCursor(mojom::CursorType type, @@ -51,7 +50,7 @@ PlatformCursor CursorFactory::CreateAnimatedCursor( mojom::CursorType type, const std::vector& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms) { + base::TimeDelta frame_delay) { NOTIMPLEMENTED(); return 0; } @@ -68,6 +67,8 @@ void CursorFactory::ObserveThemeChanges() { NOTIMPLEMENTED(); } +void CursorFactory::SetDeviceScaleFactor(float scale) {} + #if defined(OS_LINUX) || defined(OS_CHROMEOS) // Returns a cursor name compatible with either X11 or the FreeDesktop.org @@ -117,7 +118,7 @@ std::vector CursorNamesFromType(mojom::CursorType type) { case mojom::CursorType::kWestResize: return {"w-resize", "left_side"}; case mojom::CursorType::kNone: - return {"none"}; + return {}; case mojom::CursorType::kGrab: return {"openhand", "grab"}; case mojom::CursorType::kGrabbing: @@ -163,6 +164,10 @@ std::vector CursorNamesFromType(mojom::CursorType type) { case mojom::CursorType::kCopy: return {"copy"}; case mojom::CursorType::kNotAllowed: + case mojom::CursorType::kNorthSouthNoResize: + case mojom::CursorType::kEastWestNoResize: + case mojom::CursorType::kNorthEastSouthWestNoResize: + case mojom::CursorType::kNorthWestSouthEastNoResize: return {"not-allowed", "crossed_circle"}; case mojom::CursorType::kDndNone: return {"dnd-none", "hand2"}; diff --git a/chromium/ui/base/cursor/cursor_factory.h b/chromium/ui/base/cursor/cursor_factory.h index 7de026b856b..a4b25f9f56c 100644 --- a/chromium/ui/base/cursor/cursor_factory.h +++ b/chromium/ui/base/cursor/cursor_factory.h @@ -5,15 +5,19 @@ #ifndef UI_BASE_CURSOR_CURSOR_FACTORY_H_ #define UI_BASE_CURSOR_CURSOR_FACTORY_H_ +#include #include #include "base/component_export.h" -#include "base/optional.h" #include "build/build_config.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" class SkBitmap; +namespace base { +class TimeDelta; +} + namespace gfx { class Point; } @@ -32,10 +36,8 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory { // 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. - // nullptr may be a valid value for the hidden cursor. When a default cursor - // is not available, base::nullopt is returned. - virtual base::Optional GetDefaultCursor( - mojom::CursorType type); + // 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 @@ -49,12 +51,12 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory { // 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_ms| is the delay between frames in millisecond. + // |frame_delay| is the delay between frames. virtual PlatformCursor CreateAnimatedCursor( mojom::CursorType type, const std::vector& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms); + base::TimeDelta frame_delay); // Increment platform image cursor refcount. virtual void RefImageCursor(PlatformCursor cursor); @@ -65,6 +67,10 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory { // Called after CursorThemeManager is initialized, to be able to track // cursor theme and size changes. virtual void ObserveThemeChanges(); + + // Sets the device scale factor that CursorFactory may use when creating + // cursors. + virtual void SetDeviceScaleFactor(float scale); }; #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 20544e2d3f4..cdd82eb8a21 100644 --- a/chromium/ui/base/cursor/cursor_loader.cc +++ b/chromium/ui/base/cursor/cursor_loader.cc @@ -8,6 +8,7 @@ #include #include "base/check.h" +#include "base/time/time.h" #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor_factory.h" #include "ui/base/cursor/cursor_size.h" @@ -23,7 +24,8 @@ namespace { constexpr mojom::CursorType kAnimatedCursorTypes[] = { mojom::CursorType::kWait, mojom::CursorType::kProgress}; -const int kAnimatedCursorFrameDelayMs = 25; +constexpr base::TimeDelta kAnimatedCursorFrameDelay = + base::TimeDelta::FromMilliseconds(25); } // namespace @@ -49,6 +51,8 @@ bool CursorLoader::SetDisplayData(display::Display::Rotation rotation, rotation_ = rotation; scale_ = scale; UnloadCursors(); + if (use_platform_cursors_) + factory_->SetDeviceScaleFactor(scale_); return true; } @@ -83,7 +87,7 @@ void CursorLoader::LoadImageCursor(mojom::CursorType type, GetAnimatedCursorBitmaps(resource_id, scale(), rotation(), &hotspot, &bitmaps); image_cursors_[type] = factory_->CreateAnimatedCursor( - type, bitmaps, hotspot, kAnimatedCursorFrameDelayMs); + type, bitmaps, hotspot, kAnimatedCursorFrameDelay); } } @@ -95,24 +99,24 @@ 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; if (use_platform_cursors_ || type == mojom::CursorType::kNone) { - base::Optional default_cursor = - factory_->GetDefaultCursor(type); - if (default_cursor) - return *default_cursor; + cursor = factory_->GetDefaultCursor(type); + if (cursor) + return cursor; LOG(ERROR) << "Failed to load a platform cursor of type " << type; } // Loads the default Aura cursor bitmap for the cursor type. Falls back on // pointer cursor if this fails. - PlatformCursor platform = LoadCursorFromAsset(type); - if (!platform && type != mojom::CursorType::kPointer) { - platform = CursorFromType(mojom::CursorType::kPointer); - factory_->RefImageCursor(platform); - image_cursors_[type] = platform; + cursor = LoadCursorFromAsset(type); + if (!cursor && type != mojom::CursorType::kPointer) { + cursor = CursorFromType(mojom::CursorType::kPointer); + factory_->RefImageCursor(cursor); + image_cursors_[type] = cursor; } - DCHECK(platform) << "Failed to load a bitmap for the pointer cursor."; - return platform; + DCHECK(cursor) << "Failed to load a bitmap for the pointer cursor."; + return cursor; } PlatformCursor CursorLoader::LoadCursorFromAsset(mojom::CursorType type) { diff --git a/chromium/ui/base/cursor/cursor_loader_unittest.cc b/chromium/ui/base/cursor/cursor_loader_unittest.cc index a609fa4e554..c50a3f2c53f 100644 --- a/chromium/ui/base/cursor/cursor_loader_unittest.cc +++ b/chromium/ui/base/cursor/cursor_loader_unittest.cc @@ -4,7 +4,6 @@ #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" @@ -50,7 +49,10 @@ TEST(CursorLoaderTest, InvisibleCursor) { #if defined(USE_OZONE) && !defined(USE_X11) TEST(CursorLoaderTest, InvisibleCursor) { BitmapCursorFactoryOzone cursor_factory; - EXPECT_EQ(LoadInvisibleCursor(), nullptr); + auto* invisible_cursor = + static_cast(LoadInvisibleCursor()); + ASSERT_NE(invisible_cursor, nullptr); + EXPECT_EQ(invisible_cursor->type(), mojom::CursorType::kNone); } #endif @@ -61,7 +63,8 @@ TEST(CursorLoaderTest, InvisibleCursor) { // invisible cursor in X11. auto* invisible_cursor = cursor_factory.CreateImageCursor({}, SkBitmap(), gfx::Point()); - EXPECT_EQ(LoadInvisibleCursor(), invisible_cursor); + ASSERT_NE(invisible_cursor, nullptr); + EXPECT_EQ(invisible_cursor, LoadInvisibleCursor()); // Release our refcount on the cursor cursor_factory.UnrefImageCursor(invisible_cursor); diff --git a/chromium/ui/base/cursor/cursors_aura.cc b/chromium/ui/base/cursor/cursors_aura.cc index c63ea7594e4..2a63023f112 100644 --- a/chromium/ui/base/cursor/cursors_aura.cc +++ b/chromium/ui/base/cursor/cursors_aura.cc @@ -108,18 +108,34 @@ const CursorData kNormalCursors[] = { IDR_AURA_CURSOR_COL_RESIZE, {12, 11}, {25, 23}}, + {mojom::CursorType::kEastWestNoResize, + IDR_AURA_CURSOR_EAST_WEST_NO_RESIZE, + {12, 11}, + {25, 23}}, {mojom::CursorType::kEastWestResize, IDR_AURA_CURSOR_EAST_WEST_RESIZE, {12, 11}, {25, 23}}, + {mojom::CursorType::kNorthSouthNoResize, + IDR_AURA_CURSOR_NORTH_SOUTH_NO_RESIZE, + {11, 12}, + {23, 23}}, {mojom::CursorType::kNorthSouthResize, IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, {11, 12}, {23, 23}}, + {mojom::CursorType::kNorthEastSouthWestNoResize, + IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_NO_RESIZE, + {12, 11}, + {25, 23}}, {mojom::CursorType::kNorthEastSouthWestResize, IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, {12, 11}, {25, 23}}, + {mojom::CursorType::kNorthWestSouthEastNoResize, + IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_NO_RESIZE, + {11, 11}, + {24, 23}}, {mojom::CursorType::kNorthWestSouthEastResize, IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, {11, 11}, @@ -213,18 +229,34 @@ const CursorData kLargeCursors[] = { IDR_AURA_CURSOR_BIG_COL_RESIZE, {35, 29}, {70, 58}}, + {mojom::CursorType::kEastWestNoResize, + IDR_AURA_CURSOR_BIG_EAST_WEST_NO_RESIZE, + {35, 29}, + {70, 58}}, {mojom::CursorType::kEastWestResize, IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE, {35, 29}, {70, 58}}, + {mojom::CursorType::kNorthSouthNoResize, + IDR_AURA_CURSOR_BIG_NORTH_SOUTH_NO_RESIZE, + {29, 32}, + {58, 64}}, {mojom::CursorType::kNorthSouthResize, IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE, {29, 32}, {58, 64}}, + {mojom::CursorType::kNorthEastSouthWestNoResize, + IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_NO_RESIZE, + {32, 30}, + {64, 60}}, {mojom::CursorType::kNorthEastSouthWestResize, IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE, {32, 30}, {64, 60}}, + {mojom::CursorType::kNorthWestSouthEastNoResize, + IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_NO_RESIZE, + {32, 31}, + {64, 62}}, {mojom::CursorType::kNorthWestSouthEastResize, IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE, {32, 31}, @@ -309,9 +341,10 @@ SkBitmap GetDefaultBitmap(const Cursor& cursor) { cursor.image_scale_factor(), &resource_id, &hotspot)) { return SkBitmap(); } - return *ResourceBundle::GetSharedInstance() - .GetImageSkiaNamed(resource_id) - ->bitmap(); + return ResourceBundle::GetSharedInstance() + .GetImageSkiaNamed(resource_id) + ->GetRepresentation(cursor.image_scale_factor()) + .GetBitmap(); #endif } diff --git a/chromium/ui/base/cursor/mojom/cursor_type.mojom b/chromium/ui/base/cursor/mojom/cursor_type.mojom index c3dd2db1b87..36e4370e76d 100644 --- a/chromium/ui/base/cursor/mojom/cursor_type.mojom +++ b/chromium/ui/base/cursor/mojom/cursor_type.mojom @@ -60,4 +60,8 @@ enum CursorType { kDndMove, kDndCopy, kDndLink, + kEastWestNoResize, + kNorthSouthNoResize, + kNorthEastSouthWestNoResize, + kNorthWestSouthEastNoResize, }; 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 1fbb8d5d6ad..189a61bd851 100644 --- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc +++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc @@ -7,7 +7,9 @@ #include #include "base/check_op.h" +#include "base/memory/scoped_refptr.h" #include "base/notreached.h" +#include "base/time/time.h" #include "build/chromeos_buildflags.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" @@ -74,6 +76,10 @@ bool UseDefaultCursorForType(mojom::CursorType type) { case CursorType::kMiddlePanningVertical: case CursorType::kMiddlePanningHorizontal: case CursorType::kCustom: + case CursorType::kEastWestNoResize: + case CursorType::kNorthEastSouthWestNoResize: + case CursorType::kNorthSouthNoResize: + case CursorType::kNorthWestSouthEastNoResize: return false; } } @@ -89,13 +95,12 @@ PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) { } // namespace -BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type) - : type_(type), frame_delay_ms_(0) {} +BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type) : type_(type) {} BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type, const SkBitmap& bitmap, const gfx::Point& hotspot) - : type_(type), hotspot_(hotspot), frame_delay_ms_(0) { + : type_(type), hotspot_(hotspot) { if (!bitmap.isNull()) bitmaps_.push_back(bitmap); } @@ -103,13 +108,13 @@ BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type, BitmapCursorOzone::BitmapCursorOzone(mojom::CursorType type, const std::vector& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms) + base::TimeDelta frame_delay) : type_(type), bitmaps_(bitmaps), hotspot_(hotspot), - frame_delay_ms_(frame_delay_ms) { + frame_delay_(frame_delay) { DCHECK_LT(0U, bitmaps.size()); - DCHECK_LE(0, frame_delay_ms); + DCHECK_LE(base::TimeDelta(), frame_delay); // No null bitmap should be in the list. Blank cursors should just be an empty // vector. DCHECK(std::find_if(bitmaps_.begin(), bitmaps_.end(), @@ -135,8 +140,8 @@ const std::vector& BitmapCursorOzone::bitmaps() { return bitmaps_; } -int BitmapCursorOzone::frame_delay_ms() { - return frame_delay_ms_; +base::TimeDelta BitmapCursorOzone::frame_delay() { + return frame_delay_; } BitmapCursorFactoryOzone::BitmapCursorFactoryOzone() {} @@ -149,20 +154,25 @@ scoped_refptr BitmapCursorFactoryOzone::GetBitmapCursor( return base::WrapRefCounted(ToBitmapCursorOzone(platform_cursor)); } -base::Optional BitmapCursorFactoryOzone::GetDefaultCursor( +PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor( mojom::CursorType type) { - if (type == mojom::CursorType::kNone) - return nullptr; // nullptr is used for the hidden cursor. + if (!default_cursors_.count(type)) { + if (type == mojom::CursorType::kNone #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (UseDefaultCursorForType(type)) { - // Lacros uses server-side cursors for most types. These cursors don't need - // to load bitmap images on the client. - BitmapCursorOzone* cursor = new BitmapCursorOzone(type); - cursor->AddRef(); // Balanced by UnrefImageCursor. - return ToPlatformCursor(cursor); + || UseDefaultCursorForType(type) +#endif + ) { + // Lacros uses server-side cursors for most types. These cursors don't + // need to load bitmap images on the client. + // Similarly, the hidden cursor doesn't use any bitmap. + default_cursors_[type] = base::MakeRefCounted(type); + } else { + return nullptr; + } } -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - return base::nullopt; + + // Returns owned default cursor for this type. + return default_cursors_[type].get(); } PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor( @@ -178,12 +188,12 @@ PlatformCursor BitmapCursorFactoryOzone::CreateAnimatedCursor( mojom::CursorType type, const std::vector& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms) { + base::TimeDelta frame_delay) { DCHECK_LT(0U, bitmaps.size()); - BitmapCursorOzone* cursor = - new BitmapCursorOzone(type, bitmaps, hotspot, frame_delay_ms); + auto cursor = base::MakeRefCounted(type, bitmaps, hotspot, + frame_delay); cursor->AddRef(); // Balanced by UnrefImageCursor. - return ToPlatformCursor(cursor); + return ToPlatformCursor(cursor.get()); } void BitmapCursorFactoryOzone::RefImageCursor(PlatformCursor cursor) { 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 0fa94409e0c..e59398136b0 100644 --- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h +++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h @@ -5,11 +5,14 @@ #ifndef UI_BASE_CURSOR_OZONE_BITMAP_CURSOR_FACTORY_OZONE_H_ #define UI_BASE_CURSOR_OZONE_BITMAP_CURSOR_FACTORY_OZONE_H_ +#include #include #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" @@ -35,7 +38,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone BitmapCursorOzone(mojom::CursorType type, const std::vector& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms); + base::TimeDelta frame_delay); // Creates a cursor with external storage. BitmapCursorOzone(mojom::CursorType type, void* platform_data); @@ -46,7 +49,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone // For animated cursors. const std::vector& bitmaps(); - int frame_delay_ms(); + base::TimeDelta frame_delay(); // For theme cursors. void* platform_data() { return platform_data_; } @@ -58,7 +61,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone const mojom::CursorType type_; std::vector bitmaps_; gfx::Point hotspot_; - int frame_delay_ms_; + base::TimeDelta frame_delay_; // Platform cursor data. Having this non-nullptr means that this cursor // is supplied by the platform. @@ -81,20 +84,22 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorFactoryOzone static scoped_refptr GetBitmapCursor( PlatformCursor platform_cursor); - // CursorFactoryOzone: - base::Optional GetDefaultCursor( - mojom::CursorType type) 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& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms) override; + base::TimeDelta frame_delay) override; void RefImageCursor(PlatformCursor cursor) override; void UnrefImageCursor(PlatformCursor cursor) override; private: + std::map> + default_cursors_; + DISALLOW_COPY_AND_ASSIGN(BitmapCursorFactoryOzone); }; 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 3ed24fe7047..21e2984c3d7 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 @@ -4,7 +4,6 @@ #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" -#include "base/optional.h" #include "build/chromeos_buildflags.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/cursor/cursor.h" @@ -12,14 +11,16 @@ namespace ui { +using mojom::CursorType; + TEST(BitmapCursorFactoryOzoneTest, InvisibleCursor) { BitmapCursorFactoryOzone cursor_factory; - base::Optional cursor = - cursor_factory.GetDefaultCursor(mojom::CursorType::kNone); - // The invisible cursor should be nullptr, not base::nullopt. - ASSERT_TRUE(cursor.has_value()); - EXPECT_EQ(cursor, nullptr); + PlatformCursor 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(cursor)->type(), CursorType::kNone); } #if BUILDFLAG(IS_CHROMEOS_LACROS) @@ -27,29 +28,26 @@ TEST(BitmapCursorFactoryOzoneTest, LacrosUsesDefaultCursorsForCommonTypes) { BitmapCursorFactoryOzone factory; // Verify some common cursor types. - base::Optional cursor = - factory.GetDefaultCursor(mojom::CursorType::kPointer); - ASSERT_TRUE(cursor.has_value()); + PlatformCursor cursor = factory.GetDefaultCursor(CursorType::kPointer); EXPECT_NE(cursor, nullptr); - factory.UnrefImageCursor(cursor.value()); + EXPECT_EQ(static_cast(cursor)->type(), + CursorType::kPointer); - cursor = factory.GetDefaultCursor(mojom::CursorType::kHand); - ASSERT_TRUE(cursor.has_value()); + cursor = factory.GetDefaultCursor(CursorType::kHand); EXPECT_NE(cursor, nullptr); - factory.UnrefImageCursor(cursor.value()); + EXPECT_EQ(static_cast(cursor)->type(), CursorType::kHand); - cursor = factory.GetDefaultCursor(mojom::CursorType::kIBeam); - ASSERT_TRUE(cursor.has_value()); + cursor = factory.GetDefaultCursor(CursorType::kIBeam); EXPECT_NE(cursor, nullptr); - factory.UnrefImageCursor(cursor.value()); + EXPECT_EQ(static_cast(cursor)->type(), + CursorType::kIBeam); } TEST(BitmapCursorFactoryOzoneTest, LacrosCustomCursor) { BitmapCursorFactoryOzone factory; - base::Optional cursor = - factory.GetDefaultCursor(mojom::CursorType::kCustom); + PlatformCursor cursor = factory.GetDefaultCursor(CursorType::kCustom); // Custom cursors don't have a default platform cursor. - EXPECT_FALSE(cursor.has_value()); + EXPECT_EQ(cursor, nullptr); } #endif // BUILDFLAG(IS_CHROMEOS_LACROS) diff --git a/chromium/ui/base/cursor/win/win_cursor_factory.cc b/chromium/ui/base/cursor/win/win_cursor_factory.cc index bde6a5be63f..abe5223eabb 100644 --- a/chromium/ui/base/cursor/win/win_cursor_factory.cc +++ b/chromium/ui/base/cursor/win/win_cursor_factory.cc @@ -10,7 +10,6 @@ #include "base/memory/scoped_refptr.h" #include "base/notreached.h" -#include "base/optional.h" #include "base/win/scoped_gdi_object.h" #include "base/win/windows_types.h" #include "ui/base/cursor/cursor.h" @@ -67,6 +66,10 @@ const wchar_t* GetCursorId(mojom::CursorType type) { return IDC_APPSTARTING; case mojom::CursorType::kNoDrop: case mojom::CursorType::kNotAllowed: + case mojom::CursorType::kEastWestNoResize: + case mojom::CursorType::kNorthEastSouthWestNoResize: + case mojom::CursorType::kNorthSouthNoResize: + case mojom::CursorType::kNorthWestSouthEastNoResize: return IDC_NO; case mojom::CursorType::kColumnResize: return MAKEINTRESOURCE(IDC_COLRESIZE); @@ -132,8 +135,7 @@ WinCursorFactory::WinCursorFactory() = default; WinCursorFactory::~WinCursorFactory() = default; -base::Optional WinCursorFactory::GetDefaultCursor( - mojom::CursorType type) { +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 @@ -146,7 +148,7 @@ base::Optional WinCursorFactory::GetDefaultCursor( if (!hcursor) hcursor = LoadCursorFromResourcesDataDLL(id); if (!hcursor) - return base::nullopt; + return nullptr; } default_cursors_[type] = base::MakeRefCounted(hcursor); } diff --git a/chromium/ui/base/cursor/win/win_cursor_factory.h b/chromium/ui/base/cursor/win/win_cursor_factory.h index 21b6c53eb71..ff8534532cd 100644 --- a/chromium/ui/base/cursor/win/win_cursor_factory.h +++ b/chromium/ui/base/cursor/win/win_cursor_factory.h @@ -29,8 +29,7 @@ class COMPONENT_EXPORT(UI_BASE_CURSOR) WinCursorFactory : public CursorFactory { ~WinCursorFactory() override; // CursorFactory: - base::Optional GetDefaultCursor( - mojom::CursorType type) override; + PlatformCursor GetDefaultCursor(mojom::CursorType type) override; PlatformCursor CreateImageCursor(mojom::CursorType type, const SkBitmap& bitmap, const gfx::Point& hotspot) override; diff --git a/chromium/ui/base/data_transfer_policy/data_transfer_policy_controller.h b/chromium/ui/base/data_transfer_policy/data_transfer_policy_controller.h index 6d7f7f2bd52..edab3d050ad 100644 --- a/chromium/ui/base/data_transfer_policy/data_transfer_policy_controller.h +++ b/chromium/ui/base/data_transfer_policy/data_transfer_policy_controller.h @@ -5,9 +5,14 @@ #ifndef UI_BASE_DATA_TRANSFER_POLICY_DATA_TRANSFER_POLICY_CONTROLLER_H_ #define UI_BASE_DATA_TRANSFER_POLICY_DATA_TRANSFER_POLICY_CONTROLLER_H_ +#include "base/callback.h" #include "base/component_export.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" +namespace content { +class WebContents; +} + namespace ui { // The DataTransfer policy controller controls transferring data via @@ -33,6 +38,17 @@ class COMPONENT_EXPORT(UI_BASE_DATA_TRANSFER_POLICY) const DataTransferEndpoint* const data_src, const DataTransferEndpoint* const data_dst) = 0; + // nullptr can be passed instead of `data_src` or `data_dst`. If clipboard + // data is set to be in warning mode, this function will show a notification + // to the user. If clipboard read is allowed, `callback` will be invoked with + // true. Otherwise `callback` will be invoked with false. + // If `web_contents` got destroyed before `callback` is invoked, the + // notification will get closed. + virtual void PasteIfAllowed(const DataTransferEndpoint* const data_src, + const DataTransferEndpoint* const data_dst, + content::WebContents* web_contents, + base::OnceCallback callback) = 0; + // nullptr can be passed instead of `data_src` or `data_dst`. If dropping the // data is not allowed, this function will show a notification to the user. virtual bool IsDragDropAllowed(const DataTransferEndpoint* const data_src, diff --git a/chromium/ui/base/dragdrop/BUILD.gn b/chromium/ui/base/dragdrop/BUILD.gn new file mode 100644 index 00000000000..82c9295dbcd --- /dev/null +++ b/chromium/ui/base/dragdrop/BUILD.gn @@ -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. + +component("types") { + output_name = "ui_base_dragdrop_types" + sources = [ + "drag_drop_types.cc", + "drag_drop_types.h", + ] + defines = [ "IS_UI_BASE_DRAGDROP_TYPES_IMPL" ] + public_deps = [ "//base" ] + deps = [ "//ui/base/dragdrop/mojom" ] + + if (is_mac) { + sources += [ "drag_drop_types_mac.mm" ] + frameworks = [ "AppKit.framework" ] + } + + if (is_win) { + sources += [ "drag_drop_types_win.cc" ] + } +} diff --git a/chromium/ui/base/dragdrop/cocoa_dnd_util.h b/chromium/ui/base/dragdrop/cocoa_dnd_util.h index 1daf898b21c..52c3b7b210c 100644 --- a/chromium/ui/base/dragdrop/cocoa_dnd_util.h +++ b/chromium/ui/base/dragdrop/cocoa_dnd_util.h @@ -7,10 +7,10 @@ #import +#include #include #include "base/component_export.h" -#include "base/strings/string16.h" class GURL; @@ -36,7 +36,7 @@ COMPONENT_EXPORT(UI_BASE) extern NSString* const kChromeDragImageHTMLPboardType; // will also attempt to convert filenames in |pboard| to file URLs. COMPONENT_EXPORT(UI_BASE) BOOL PopulateURLAndTitleFromPasteboard(GURL* url, - base::string16* title, + std::u16string* title, NSPasteboard* pboard, BOOL convert_filenames); diff --git a/chromium/ui/base/dragdrop/cocoa_dnd_util.mm b/chromium/ui/base/dragdrop/cocoa_dnd_util.mm index 0913578fc12..e53c2172a99 100644 --- a/chromium/ui/base/dragdrop/cocoa_dnd_util.mm +++ b/chromium/ui/base/dragdrop/cocoa_dnd_util.mm @@ -16,7 +16,7 @@ NSString* const kChromeDragDummyPboardType = @"org.chromium.drag-dummy-type"; NSString* const kChromeDragImageHTMLPboardType = @"org.chromium.image-html"; BOOL PopulateURLAndTitleFromPasteboard(GURL* url, - base::string16* title, + std::u16string* title, NSPasteboard* pboard, BOOL convert_filenames) { CHECK(url); diff --git a/chromium/ui/base/dragdrop/drag_drop_types.h b/chromium/ui/base/dragdrop/drag_drop_types.h index 54162dda703..8f7fbbaccc4 100644 --- a/chromium/ui/base/dragdrop/drag_drop_types.h +++ b/chromium/ui/base/dragdrop/drag_drop_types.h @@ -12,7 +12,7 @@ namespace ui { -class COMPONENT_EXPORT(UI_BASE) DragDropTypes { +class COMPONENT_EXPORT(UI_BASE_DRAGDROP_TYPES) DragDropTypes { public: // These constants match their equivalents in NSDragOperation and // should not be renumbered. diff --git a/chromium/ui/base/dragdrop/drag_drop_types_mac.mm b/chromium/ui/base/dragdrop/drag_drop_types_mac.mm index 9138df80034..febe21d4e9f 100644 --- a/chromium/ui/base/dragdrop/drag_drop_types_mac.mm +++ b/chromium/ui/base/dragdrop/drag_drop_types_mac.mm @@ -4,7 +4,7 @@ #include "ui/base/dragdrop/drag_drop_types.h" -#import +#import namespace ui { diff --git a/chromium/ui/base/dragdrop/mojom/BUILD.gn b/chromium/ui/base/dragdrop/mojom/BUILD.gn index 013709e9ee6..963d01edc2a 100644 --- a/chromium/ui/base/dragdrop/mojom/BUILD.gn +++ b/chromium/ui/base/dragdrop/mojom/BUILD.gn @@ -4,7 +4,9 @@ import("//mojo/public/tools/bindings/mojom.gni") -mojom("mojom") { +mojom_component("mojom") { + output_prefix = "ui_base_dragdrop_mojom" + macro_prefix = "UI_BASE_DRAGDROP_MOJOM" generate_java = true sources = [ "drag_drop_types.mojom" ] } diff --git a/chromium/ui/base/dragdrop/os_exchange_data.cc b/chromium/ui/base/dragdrop/os_exchange_data.cc index 9d708acc056..30d06ec5b14 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data.cc @@ -34,11 +34,11 @@ bool OSExchangeData::DidOriginateFromRenderer() const { return provider_->DidOriginateFromRenderer(); } -void OSExchangeData::SetString(const base::string16& data) { +void OSExchangeData::SetString(const std::u16string& data) { provider_->SetString(data); } -void OSExchangeData::SetURL(const GURL& url, const base::string16& title) { +void OSExchangeData::SetURL(const GURL& url, const std::u16string& title) { provider_->SetURL(url, title); } @@ -56,13 +56,13 @@ void OSExchangeData::SetPickledData(const ClipboardFormatType& format, provider_->SetPickledData(format, data); } -bool OSExchangeData::GetString(base::string16* data) const { +bool OSExchangeData::GetString(std::u16string* data) const { return provider_->GetString(data); } bool OSExchangeData::GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const { + std::u16string* title) const { return provider_->GetURLAndTitle(policy, url, title); } @@ -152,11 +152,11 @@ bool OSExchangeData::HasHtml() const { return provider_->HasHtml(); } -void OSExchangeData::SetHtml(const base::string16& html, const GURL& base_url) { +void OSExchangeData::SetHtml(const std::u16string& html, const GURL& base_url) { provider_->SetHtml(html, base_url); } -bool OSExchangeData::GetHtml(base::string16* html, GURL* base_url) const { +bool OSExchangeData::GetHtml(std::u16string* html, GURL* base_url) const { return provider_->GetHtml(html, base_url); } #endif diff --git a/chromium/ui/base/dragdrop/os_exchange_data.h b/chromium/ui/base/dragdrop/os_exchange_data.h index 067e2108655..abaaf8a28f3 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data.h +++ b/chromium/ui/base/dragdrop/os_exchange_data.h @@ -92,9 +92,9 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData { // the order of enumeration in our IEnumFORMATETC implementation! // This comes into play when selecting the best (most preferable) // data type for insertion into a DropTarget. - void SetString(const base::string16& data); + void SetString(const std::u16string& data); // A URL can have an optional title in some exchange formats. - void SetURL(const GURL& url, const base::string16& title); + void SetURL(const GURL& url, const std::u16string& title); // A full path to a file. void SetFilename(const base::FilePath& path); // Full path to one or more files. See also SetFilenames() in Provider. @@ -110,10 +110,10 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData { // NULL. // GetString() returns the plain text representation of the pasteboard // contents. - bool GetString(base::string16* data) const; + bool GetString(std::u16string* data) const; bool GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const; + std::u16string* title) const; // Return the path of a file, if available. bool GetFilename(base::FilePath* path) const; bool GetFilenames(std::vector* file_names) const; @@ -182,8 +182,8 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeData { #if defined(USE_AURA) // Adds a snippet of HTML. |html| is just raw html but this sets both // text/html and CF_HTML. - void SetHtml(const base::string16& html, const GURL& base_url); - bool GetHtml(base::string16* html, GURL* base_url) const; + void SetHtml(const std::u16string& html, const GURL& base_url); + bool GetHtml(std::u16string* html, GURL* base_url) const; bool HasHtml() const; #endif diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider.h b/chromium/ui/base/dragdrop/os_exchange_data_provider.h index 32c95b457dd..5d121e1daf9 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider.h @@ -17,7 +17,6 @@ #include "base/component_export.h" #include "base/files/file_path.h" -#include "base/strings/string16.h" #include "ui/base/clipboard/clipboard_format_type.h" #include "ui/base/clipboard/file_info.h" #include "ui/base/dragdrop/download_file_info.h" @@ -52,17 +51,17 @@ class COMPONENT_EXPORT(UI_BASE_DATA_EXCHANGE) OSExchangeDataProvider { virtual void MarkOriginatedFromRenderer() = 0; virtual bool DidOriginateFromRenderer() const = 0; - virtual void SetString(const base::string16& data) = 0; - virtual void SetURL(const GURL& url, const base::string16& title) = 0; + virtual void SetString(const std::u16string& data) = 0; + virtual void SetURL(const GURL& url, const std::u16string& title) = 0; virtual void SetFilename(const base::FilePath& path) = 0; virtual void SetFilenames(const std::vector& file_names) = 0; virtual void SetPickledData(const ClipboardFormatType& format, const base::Pickle& data) = 0; - virtual bool GetString(base::string16* data) const = 0; + virtual bool GetString(std::u16string* data) const = 0; virtual bool GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const = 0; + std::u16string* title) const = 0; virtual bool GetFilename(base::FilePath* path) const = 0; virtual bool GetFilenames(std::vector* file_names) const = 0; virtual bool GetPickledData(const ClipboardFormatType& format, @@ -73,14 +72,12 @@ class COMPONENT_EXPORT(UI_BASE_DATA_EXCHANGE) OSExchangeDataProvider { virtual bool HasFile() const = 0; virtual bool HasCustomFormat(const ClipboardFormatType& format) const = 0; -#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN) virtual void SetFileContents(const base::FilePath& filename, const std::string& file_contents) = 0; -#endif -#if defined(OS_WIN) virtual bool GetFileContents(base::FilePath* filename, std::string* file_contents) const = 0; virtual bool HasFileContents() const = 0; +#if defined(OS_WIN) virtual bool HasVirtualFilenames() const = 0; virtual bool GetVirtualFilenames(std::vector* file_names) const = 0; virtual bool GetVirtualFilesAsTempFiles( @@ -96,8 +93,8 @@ class COMPONENT_EXPORT(UI_BASE_DATA_EXCHANGE) OSExchangeDataProvider { #endif #if defined(USE_AURA) - virtual void SetHtml(const base::string16& html, const GURL& base_url) = 0; - virtual bool GetHtml(base::string16* html, GURL* base_url) const = 0; + virtual void SetHtml(const std::u16string& html, const GURL& base_url) = 0; + virtual bool GetHtml(std::u16string* html, GURL* base_url) const = 0; virtual bool HasHtml() const = 0; #endif diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h index 1626a146078..ad8c562fe92 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h @@ -42,16 +42,16 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderMac // Overridden from OSExchangeDataProvider: void MarkOriginatedFromRenderer() override; bool DidOriginateFromRenderer() const override; - void SetString(const base::string16& data) override; - void SetURL(const GURL& url, const base::string16& title) override; + void SetString(const std::u16string& data) override; + void SetURL(const GURL& url, const std::u16string& title) override; void SetFilename(const base::FilePath& path) override; void SetFilenames(const std::vector& filenames) override; void SetPickledData(const ClipboardFormatType& format, const base::Pickle& data) override; - bool GetString(base::string16* data) const override; + bool GetString(std::u16string* data) const override; bool GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const override; + std::u16string* title) const override; bool GetFilename(base::FilePath* path) const override; bool GetFilenames(std::vector* filenames) const override; bool GetPickledData(const ClipboardFormatType& format, @@ -60,6 +60,11 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderMac bool HasURL(FilenameToURLPolicy policy) const override; bool HasFile() const override; bool HasCustomFormat(const ClipboardFormatType& format) const override; + void SetFileContents(const base::FilePath& filename, + const std::string& file_contents) override; + bool GetFileContents(base::FilePath* filename, + std::string* file_contents) const override; + bool HasFileContents() const override; void SetDragImage(const gfx::ImageSkia& image, const gfx::Vector2d& cursor_offset) override; gfx::ImageSkia GetDragImage() const override; diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm index 98daf64f30b..3f501500b42 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm @@ -144,13 +144,13 @@ bool OSExchangeDataProviderMac::DidOriginateFromRenderer() const { return false; } -void OSExchangeDataProviderMac::SetString(const base::string16& string) { +void OSExchangeDataProviderMac::SetString(const std::u16string& string) { [GetPasteboard() setString:base::SysUTF16ToNSString(string) forType:NSPasteboardTypeString]; } void OSExchangeDataProviderMac::SetURL(const GURL& url, - const base::string16& title) { + const std::u16string& title) { base::scoped_nsobject item = ClipboardUtil::PasteboardItemFromUrl(base::SysUTF8ToNSString(url.spec()), base::SysUTF16ToNSString(title)); @@ -183,7 +183,7 @@ void OSExchangeDataProviderMac::SetPickledData( [GetPasteboard() setData:ns_data forType:format.ToNSString()]; } -bool OSExchangeDataProviderMac::GetString(base::string16* data) const { +bool OSExchangeDataProviderMac::GetString(std::u16string* data) const { DCHECK(data); NSString* item = [GetPasteboard() stringForType:NSPasteboardTypeString]; if (item) { @@ -193,7 +193,7 @@ bool OSExchangeDataProviderMac::GetString(base::string16* data) const { // There was no NSString, check for an NSURL. GURL url; - base::string16 title; + std::u16string title; bool result = GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &url, &title); if (result) @@ -204,7 +204,7 @@ bool OSExchangeDataProviderMac::GetString(base::string16* data) const { bool OSExchangeDataProviderMac::GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const { + std::u16string* title) const { DCHECK(url); DCHECK(title); @@ -268,13 +268,13 @@ bool OSExchangeDataProviderMac::GetPickledData( } bool OSExchangeDataProviderMac::HasString() const { - base::string16 string; + std::u16string string; return GetString(&string); } bool OSExchangeDataProviderMac::HasURL(FilenameToURLPolicy policy) const { GURL url; - base::string16 title; + std::u16string title; return GetURLAndTitle(policy, &url, &title); } @@ -287,6 +287,24 @@ bool OSExchangeDataProviderMac::HasCustomFormat( return [[GetPasteboard() types] containsObject:format.ToNSString()]; } +void OSExchangeDataProviderMac::SetFileContents( + const base::FilePath& filename, + const std::string& file_contents) { + NOTIMPLEMENTED(); +} + +bool OSExchangeDataProviderMac::GetFileContents( + base::FilePath* filename, + std::string* file_contents) const { + NOTIMPLEMENTED(); + return false; +} + +bool OSExchangeDataProviderMac::HasFileContents() const { + NOTIMPLEMENTED(); + return false; +} + void OSExchangeDataProviderMac::SetDragImage( const gfx::ImageSkia& image, const gfx::Vector2d& cursor_offset) { diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc index 61dd3b457a7..ef3b1fe29ef 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc @@ -5,10 +5,10 @@ #include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h" #include +#include #include "base/check.h" #include "base/files/file_path.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "build/chromeos_buildflags.h" #include "net/base/filename_util.h" @@ -35,6 +35,8 @@ std::unique_ptr OSExchangeDataProviderNonBacked::Clone() clone->filenames_ = filenames_; clone->pickle_data_ = pickle_data_; // We skip copying the drag images. + clone->file_contents_filename_ = file_contents_filename_; + clone->file_contents_ = file_contents_; clone->html_ = html_; clone->base_url_ = base_url_; clone->source_ = @@ -63,7 +65,7 @@ bool OSExchangeDataProviderNonBacked::DidOriginateFromRenderer() const { #endif } -void OSExchangeDataProviderNonBacked::SetString(const base::string16& data) { +void OSExchangeDataProviderNonBacked::SetString(const std::u16string& data) { if (HasString()) return; @@ -72,7 +74,7 @@ void OSExchangeDataProviderNonBacked::SetString(const base::string16& data) { } void OSExchangeDataProviderNonBacked::SetURL(const GURL& url, - const base::string16& title) { + const std::u16string& title) { url_ = url; title_ = title; formats_ |= OSExchangeData::URL; @@ -99,7 +101,7 @@ void OSExchangeDataProviderNonBacked::SetPickledData( formats_ |= OSExchangeData::PICKLED_DATA; } -bool OSExchangeDataProviderNonBacked::GetString(base::string16* data) const { +bool OSExchangeDataProviderNonBacked::GetString(std::u16string* data) const { #if defined(OS_LINUX) || defined(OS_CHROMEOS) if (HasFile()) { // Various Linux file managers both pass a list of file:// URIs and set the @@ -118,7 +120,7 @@ bool OSExchangeDataProviderNonBacked::GetString(base::string16* data) const { bool OSExchangeDataProviderNonBacked::GetURLAndTitle( FilenameToURLPolicy policy, GURL* url, - base::string16* title) const { + std::u16string* title) const { if ((formats_ & OSExchangeData::URL) == 0) { title->clear(); return GetPlainTextURL(url) || @@ -184,22 +186,36 @@ bool OSExchangeDataProviderNonBacked::HasCustomFormat( return base::Contains(pickle_data_, format); } -#if defined(OS_LINUX) || defined(OS_CHROMEOS) void OSExchangeDataProviderNonBacked::SetFileContents( const base::FilePath& filename, const std::string& file_contents) { - NOTIMPLEMENTED(); + file_contents_filename_ = filename; + file_contents_ = file_contents; +} + +bool OSExchangeDataProviderNonBacked::GetFileContents( + base::FilePath* filename, + std::string* file_contents) const { + if (file_contents_filename_.empty()) { + return false; + } + *filename = file_contents_filename_; + *file_contents = file_contents_; + return true; +} + +bool OSExchangeDataProviderNonBacked::HasFileContents() const { + return !file_contents_filename_.empty(); } -#endif -void OSExchangeDataProviderNonBacked::SetHtml(const base::string16& html, +void OSExchangeDataProviderNonBacked::SetHtml(const std::u16string& html, const GURL& base_url) { formats_ |= OSExchangeData::HTML; html_ = html; base_url_ = base_url; } -bool OSExchangeDataProviderNonBacked::GetHtml(base::string16* html, +bool OSExchangeDataProviderNonBacked::GetHtml(std::u16string* html, GURL* base_url) const { if ((formats_ & OSExchangeData::HTML) == 0) return false; diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.h index 40f9bd82890..afee2ac6918 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.h @@ -43,16 +43,16 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked std::unique_ptr Clone() const override; void MarkOriginatedFromRenderer() override; bool DidOriginateFromRenderer() const override; - void SetString(const base::string16& data) override; - void SetURL(const GURL& url, const base::string16& title) override; + void SetString(const std::u16string& data) override; + void SetURL(const GURL& url, const std::u16string& title) override; void SetFilename(const base::FilePath& path) override; void SetFilenames(const std::vector& filenames) override; void SetPickledData(const ClipboardFormatType& format, const base::Pickle& data) override; - bool GetString(base::string16* data) const override; + bool GetString(std::u16string* data) const override; bool GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const override; + std::u16string* title) const override; bool GetFilename(base::FilePath* path) const override; bool GetFilenames(std::vector* filenames) const override; bool GetPickledData(const ClipboardFormatType& format, @@ -61,13 +61,14 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked bool HasURL(FilenameToURLPolicy policy) const override; bool HasFile() const override; bool HasCustomFormat(const ClipboardFormatType& format) const override; -#if defined(OS_LINUX) || defined(OS_CHROMEOS) void SetFileContents(const base::FilePath& filename, const std::string& file_contents) override; -#endif + bool GetFileContents(base::FilePath* filename, + std::string* file_contents) const override; + bool HasFileContents() const override; - void SetHtml(const base::string16& html, const GURL& base_url) override; - bool GetHtml(base::string16* html, GURL* base_url) const override; + void SetHtml(const std::u16string& html, const GURL& base_url) override; + bool GetHtml(std::u16string* html, GURL* base_url) const override; bool HasHtml() const override; void SetDragImage(const gfx::ImageSkia& image, const gfx::Vector2d& cursor_offset) override; @@ -91,11 +92,11 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked int formats_ = 0; // String contents. - base::string16 string_; + std::u16string string_; // URL contents. GURL url_; - base::string16 title_; + std::u16string title_; // File name. std::vector filenames_; @@ -107,8 +108,12 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked gfx::ImageSkia drag_image_; gfx::Vector2d drag_image_offset_; + // For file contents. + base::FilePath file_contents_filename_; + std::string file_contents_; + // For HTML format - base::string16 html_; + std::u16string html_; GURL base_url_; #if !BUILDFLAG(IS_CHROMEOS_ASH) 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 25240c6144c..3030bd9bb77 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 @@ -9,7 +9,6 @@ #include "base/files/file_path.h" #include "base/logging.h" -#include "base/strings/string16.h" #include "base/strings/string_piece_forward.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,6 +22,9 @@ const char kTestString[] = "Hello World!"; const char kUrl[] = "https://example.com"; const char kUrlTitle[] = "example"; const char kFileName[] = "file.pdf"; +const base::FilePath::CharType kFileContentsFileName[] = + FILE_PATH_LITERAL("file.jpg"); +const char kFileContents[] = "test data"; const char kHtml[] = "

Random Title

"; const char kBaseUrl[] = "www.example2.com"; } // namespace @@ -39,6 +41,8 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) { original_pickle.WriteString16(base::UTF8ToUTF16(kTestString)); original.SetPickledData(ClipboardFormatType::GetPlainTextType(), original_pickle); + original.SetFileContents(base::FilePath(kFileContentsFileName), + std::string(kFileContents)); original.SetHtml(base::UTF8ToUTF16(kHtml), GURL(kBaseUrl)); #if !BUILDFLAG(IS_CHROMEOS_ASH) original.MarkOriginatedFromRenderer(); @@ -47,12 +51,12 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) { original.SetSource(std::make_unique(origin)); std::unique_ptr copy = original.Clone(); - base::string16 copy_string; + std::u16string copy_string; EXPECT_TRUE(copy->GetString(©_string)); EXPECT_EQ(base::UTF8ToUTF16(kTestString), copy_string); GURL copy_url; - base::string16 copy_title; + std::u16string copy_title; EXPECT_TRUE(copy->GetURLAndTitle( FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, ©_url, ©_title)); EXPECT_EQ(GURL(kUrl), copy_url); @@ -61,11 +65,17 @@ TEST(OSExchangeDataProviderNonBackedTest, CloneTest) { base::Pickle copy_pickle; copy->GetPickledData(ClipboardFormatType::GetPlainTextType(), ©_pickle); base::PickleIterator pickle_itr(copy_pickle); - base::string16 copy_pickle_string; + std::u16string copy_pickle_string; EXPECT_TRUE(pickle_itr.ReadString16(©_pickle_string)); EXPECT_EQ(base::UTF8ToUTF16(kTestString), copy_pickle_string); - base::string16 copy_html; + base::FilePath copy_file_contents_filename; + std::string copy_file_contents; + copy->GetFileContents(©_file_contents_filename, ©_file_contents); + EXPECT_EQ(base::FilePath(kFileContentsFileName), copy_file_contents_filename); + EXPECT_EQ(std::string(kFileContents), copy_file_contents); + + std::u16string copy_html; GURL copy_base_url; EXPECT_TRUE(copy->GetHtml(©_html, ©_base_url)); EXPECT_EQ(base::UTF8ToUTF16(kHtml), copy_html); @@ -91,4 +101,4 @@ TEST(OSExchangeDataProviderNonBackedTest, FileNameCloneTest) { EXPECT_EQ(base::FilePath(kFileName), copy_file_path); } -} // namespace ui \ No newline at end of file +} // namespace ui diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc index 53dd7a63945..e6d06aa2b29 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc @@ -240,7 +240,7 @@ FormatEtcEnumerator* FormatEtcEnumerator::CloneFromOther( // static bool OSExchangeDataProviderWin::HasPlainTextURL(IDataObject* source) { - base::string16 plain_text; + std::u16string plain_text; return (ClipboardUtil::GetPlainText(source, &plain_text) && !plain_text.empty() && GURL(plain_text).is_valid()); } @@ -248,7 +248,7 @@ bool OSExchangeDataProviderWin::HasPlainTextURL(IDataObject* source) { // static bool OSExchangeDataProviderWin::GetPlainTextURL(IDataObject* source, GURL* url) { - base::string16 plain_text; + std::u16string plain_text; if (ClipboardUtil::GetPlainText(source, &plain_text) && !plain_text.empty()) { GURL gurl(plain_text); @@ -302,7 +302,7 @@ bool OSExchangeDataProviderWin::DidOriginateFromRenderer() const { return HasCustomFormat(GetRendererTaintFormatType()); } -void OSExchangeDataProviderWin::SetString(const base::string16& data) { +void OSExchangeDataProviderWin::SetString(const std::u16string& data) { STGMEDIUM storage = CreateStorageForString(data); data_->contents_.push_back(DataObjectImpl::StoredDataInfo::TakeStorageMedium( ClipboardFormatType::GetPlainTextType().ToFormatEtc(), storage)); @@ -314,7 +314,7 @@ void OSExchangeDataProviderWin::SetString(const base::string16& data) { } void OSExchangeDataProviderWin::SetURL(const GURL& url, - const base::string16& title) { + const std::u16string& title) { // NOTE WELL: // Every time you change the order of the first two CLIPFORMATS that get // added here, you need to update the EnumerationViaCOM test case in @@ -322,7 +322,7 @@ void OSExchangeDataProviderWin::SetURL(const GURL& url, // will fail! It assumes an insertion order. // Add text/x-moz-url for drags from Firefox - base::string16 x_moz_url_str = base::UTF8ToUTF16(url.spec()); + std::u16string x_moz_url_str = base::UTF8ToUTF16(url.spec()); x_moz_url_str += '\n'; x_moz_url_str += title; STGMEDIUM storage = CreateStorageForString(x_moz_url_str); @@ -504,7 +504,7 @@ void OSExchangeDataProviderWin::SetFileContents( storage_contents)); } -void OSExchangeDataProviderWin::SetHtml(const base::string16& html, +void OSExchangeDataProviderWin::SetHtml(const std::u16string& html, const GURL& base_url) { // Add both MS CF_HTML and text/html format. CF_HTML should be in utf-8. std::string utf8_html = base::UTF16ToUTF8(html); @@ -521,14 +521,14 @@ void OSExchangeDataProviderWin::SetHtml(const base::string16& html, ClipboardFormatType::GetTextHtmlType().ToFormatEtc(), storage_plain)); } -bool OSExchangeDataProviderWin::GetString(base::string16* data) const { +bool OSExchangeDataProviderWin::GetString(std::u16string* data) const { return ClipboardUtil::GetPlainText(source_object_.Get(), data); } bool OSExchangeDataProviderWin::GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const { - base::string16 url_str; + std::u16string* title) const { + std::u16string url_str; bool success = ClipboardUtil::GetUrl( source_object_.Get(), url, title, policy == FilenameToURLPolicy::CONVERT_FILENAMES ? true : false); @@ -630,7 +630,7 @@ bool OSExchangeDataProviderWin::GetFileContents( return true; } -bool OSExchangeDataProviderWin::GetHtml(base::string16* html, +bool OSExchangeDataProviderWin::GetHtml(std::u16string* html, GURL* base_url) const { std::string url; bool success = ClipboardUtil::GetHtml(source_object_.Get(), html, &url); 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 447a3efdba1..6b19f7152d2 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h @@ -145,8 +145,8 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderWin std::unique_ptr Clone() const override; void MarkOriginatedFromRenderer() override; bool DidOriginateFromRenderer() const override; - void SetString(const base::string16& data) override; - void SetURL(const GURL& url, const base::string16& title) override; + void SetString(const std::u16string& data) override; + void SetURL(const GURL& url, const std::u16string& title) override; void SetFilename(const base::FilePath& path) override; void SetFilenames(const std::vector& filenames) override; // Test only method for adding virtual file content to the data store. The @@ -160,12 +160,12 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderWin const base::Pickle& data) override; void SetFileContents(const base::FilePath& filename, const std::string& file_contents) override; - void SetHtml(const base::string16& html, const GURL& base_url) override; + void SetHtml(const std::u16string& html, const GURL& base_url) override; - bool GetString(base::string16* data) const override; + bool GetString(std::u16string* data) const override; bool GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const override; + std::u16string* title) const override; bool GetFilename(base::FilePath* path) const override; bool GetFilenames(std::vector* filenames) const override; bool HasVirtualFilenames() const override; @@ -178,7 +178,7 @@ class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderWin base::Pickle* data) const override; bool GetFileContents(base::FilePath* filename, std::string* file_contents) const override; - bool GetHtml(base::string16* html, GURL* base_url) const override; + bool GetHtml(std::u16string* html, GURL* base_url) const override; bool HasString() const override; bool HasURL(FilenameToURLPolicy policy) const override; bool HasFile() const override; 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 index f2de8eb58b6..f8453a22649 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc @@ -4,7 +4,8 @@ #include "ui/base/dragdrop/os_exchange_data_provider_x11.h" -#include "base/strings/string16.h" +#include + #include "base/strings/utf_string_conversions.h" #include "base/test/task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -47,7 +48,7 @@ TEST_F(OSExchangeDataProviderX11Test, MozillaURL) { provider.SetURL(GURL(kGoogleURL), base::ASCIIToUTF16(kGoogleTitle)); { GURL out_gurl; - base::string16 out_str; + std::u16string out_str; EXPECT_TRUE(provider.GetURLAndTitle( FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); EXPECT_EQ(base::ASCIIToUTF16(kGoogleTitle), out_str); @@ -55,13 +56,13 @@ TEST_F(OSExchangeDataProviderX11Test, MozillaURL) { } // Check that we can get non-titled entries. - provider.SetURL(GURL(kGoogleURL), base::string16()); + provider.SetURL(GURL(kGoogleURL), std::u16string()); { GURL out_gurl; - base::string16 out_str; + std::u16string out_str; EXPECT_TRUE(provider.GetURLAndTitle( FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); - EXPECT_EQ(base::string16(), out_str); + EXPECT_EQ(std::u16string(), out_str); EXPECT_EQ(kGoogleURL, out_gurl.spec()); } } @@ -97,15 +98,15 @@ TEST_F(OSExchangeDataProviderX11Test, URIListWithBoth) { // We should only receive the URL here. GURL out_gurl; - base::string16 out_str; + std::u16string out_str; EXPECT_TRUE(provider.GetURLAndTitle( FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); - EXPECT_EQ(base::string16(), out_str); + EXPECT_EQ(std::u16string(), out_str); EXPECT_EQ(kGoogleURL, out_gurl.spec()); } TEST_F(OSExchangeDataProviderX11Test, OnlyStringURLIsUnfiltered) { - const base::string16 file_url = base::UTF8ToUTF16(kFileURL); + const std::u16string file_url = base::UTF8ToUTF16(kFileURL); provider.SetString(file_url); EXPECT_TRUE(provider.HasString()); @@ -113,12 +114,12 @@ TEST_F(OSExchangeDataProviderX11Test, OnlyStringURLIsUnfiltered) { } TEST_F(OSExchangeDataProviderX11Test, StringAndURIListFilterString) { - const base::string16 file_url = base::UTF8ToUTF16(kFileURL); + const std::u16string file_url = base::UTF8ToUTF16(kFileURL); provider.SetString(file_url); AddURLList(kFileURL); EXPECT_FALSE(provider.HasString()); - base::string16 out_str; + std::u16string out_str; EXPECT_FALSE(provider.GetString(&out_str)); EXPECT_TRUE(provider.HasFile()); diff --git a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc index 3c92fb07ef1..954c93f98cc 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc @@ -34,20 +34,20 @@ class OSExchangeDataTest : public PlatformTest { TEST_F(OSExchangeDataTest, StringDataGetAndSet) { OSExchangeData data; - base::string16 input = base::ASCIIToUTF16("I can has cheezburger?"); + std::u16string input = u"I can has cheezburger?"; EXPECT_FALSE(data.HasString()); data.SetString(input); EXPECT_TRUE(data.HasString()); OSExchangeData data2( std::unique_ptr(data.provider().Clone())); - base::string16 output; + std::u16string output; EXPECT_TRUE(data2.HasString()); EXPECT_TRUE(data2.GetString(&output)); EXPECT_EQ(input, output); std::string url_spec = "http://www.goats.com/"; GURL url(url_spec); - base::string16 title; + std::u16string title; EXPECT_FALSE(data2.GetURLAndTitle( FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &url, &title)); // No URLs in |data|, so url should be untouched. @@ -58,7 +58,7 @@ TEST_F(OSExchangeDataTest, TestURLExchangeFormats) { OSExchangeData data; std::string url_spec = "http://www.google.com/"; GURL url(url_spec); - base::string16 url_title = base::ASCIIToUTF16("www.google.com"); + std::u16string url_title = u"www.google.com"; EXPECT_FALSE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); data.SetURL(url, url_title); EXPECT_TRUE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); @@ -68,14 +68,14 @@ TEST_F(OSExchangeDataTest, TestURLExchangeFormats) { // URL spec and title should match GURL output_url; - base::string16 output_title; + std::u16string output_title; EXPECT_TRUE(data2.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); EXPECT_TRUE( data2.GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &output_url, &output_title)); EXPECT_EQ(url_spec, output_url.spec()); EXPECT_EQ(url_title, output_title); - base::string16 output_string; + std::u16string output_string; // URL should be the raw text response EXPECT_TRUE(data2.GetString(&output_string)); @@ -85,19 +85,19 @@ TEST_F(OSExchangeDataTest, TestURLExchangeFormats) { // Test that setting the URL does not overwrite a previously set custom string. TEST_F(OSExchangeDataTest, URLAndString) { OSExchangeData data; - base::string16 string = base::ASCIIToUTF16("I can has cheezburger?"); + std::u16string string = u"I can has cheezburger?"; data.SetString(string); std::string url_spec = "http://www.google.com/"; GURL url(url_spec); - base::string16 url_title = base::ASCIIToUTF16("www.google.com"); + std::u16string url_title = u"www.google.com"; data.SetURL(url, url_title); - base::string16 output_string; + std::u16string output_string; EXPECT_TRUE(data.GetString(&output_string)); EXPECT_EQ(string, output_string); GURL output_url; - base::string16 output_title; + std::u16string output_title; EXPECT_TRUE(data.GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &output_url, &output_title)); EXPECT_EQ(url_spec, output_url.spec()); @@ -118,25 +118,25 @@ TEST_F(OSExchangeDataTest, TestFileToURLConversion) { { EXPECT_FALSE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); GURL actual_url; - base::string16 actual_title; + std::u16string actual_title; EXPECT_FALSE( data.GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &actual_url, &actual_title)); EXPECT_EQ(GURL(), actual_url); - EXPECT_EQ(base::string16(), actual_title); + EXPECT_EQ(std::u16string(), actual_title); } { EXPECT_TRUE(data.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL actual_url; - base::string16 actual_title; + std::u16string actual_title; EXPECT_TRUE(data.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, &actual_url, &actual_title)); // Some Mac OS versions return the URL in file://localhost form instead // of file:///, so we compare the url's path not its absolute string. EXPECT_EQ(net::FilePathToFileURL(current_directory).path(), actual_url.path()); - EXPECT_EQ(base::string16(), actual_title); + EXPECT_EQ(std::u16string(), actual_title); } EXPECT_TRUE(data.HasFile()); base::FilePath actual_path; @@ -196,7 +196,7 @@ TEST_F(OSExchangeDataTest, TestFilenames) { TEST_F(OSExchangeDataTest, TestHTML) { OSExchangeData data; GURL url("http://www.google.com/"); - base::string16 html = base::ASCIIToUTF16( + std::u16string html = base::ASCIIToUTF16( "\n\n" "bold. This is bold italic.\n" "\n"); @@ -204,7 +204,7 @@ TEST_F(OSExchangeDataTest, TestHTML) { OSExchangeData copy( std::unique_ptr(data.provider().Clone())); - base::string16 read_html; + std::u16string read_html; EXPECT_TRUE(copy.HasHtml()); EXPECT_TRUE(copy.GetHtml(&read_html, &url)); EXPECT_EQ(html, read_html); diff --git a/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc index e5485f63956..10ec539ae5b 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc @@ -188,7 +188,7 @@ TEST_F(OSExchangeDataWinTest, StringDataWritingViaCOM) { OSExchangeData data2(data.provider().Clone()); EXPECT_TRUE(data2.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL url_from_data; - base::string16 title; + std::u16string title; EXPECT_TRUE(data2.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, &url_from_data, &title)); GURL reference_url(base::AsStringPiece16(input)); @@ -236,7 +236,7 @@ TEST_F(OSExchangeDataWinTest, RemoveData) { OSExchangeData data2(data.provider().Clone()); EXPECT_TRUE(data2.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL url_from_data; - base::string16 title; + std::u16string title; EXPECT_TRUE(data2.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, &url_from_data, &title)); EXPECT_EQ(GURL(base::AsStringPiece16(input2)).spec(), url_from_data.spec()); @@ -245,7 +245,7 @@ TEST_F(OSExchangeDataWinTest, RemoveData) { TEST_F(OSExchangeDataWinTest, URLDataAccessViaCOM) { OSExchangeData data; GURL url("http://www.google.com/"); - data.SetURL(url, base::string16()); + data.SetURL(url, std::u16string()); Microsoft::WRL::ComPtr com_data( OSExchangeDataProviderWin::GetIDataObject(data)); @@ -266,8 +266,8 @@ TEST_F(OSExchangeDataWinTest, MultipleFormatsViaCOM) { OSExchangeData data; std::string url_spec = "http://www.google.com/"; GURL url(url_spec); - base::string16 text = STRING16_LITERAL("O hai googlz."); - data.SetURL(url, STRING16_LITERAL("Google")); + std::u16string text = u"O hai googlz."; + data.SetURL(url, u"Google"); data.SetString(text); Microsoft::WRL::ComPtr com_data( @@ -299,8 +299,8 @@ TEST_F(OSExchangeDataWinTest, MultipleFormatsViaCOM) { TEST_F(OSExchangeDataWinTest, EnumerationViaCOM) { OSExchangeData data; - data.SetURL(GURL("http://www.google.com/"), base::string16()); - data.SetString(STRING16_LITERAL("O hai googlz.")); + data.SetURL(GURL("http://www.google.com/"), std::u16string()); + data.SetString(u"O hai googlz."); CLIPFORMAT cfstr_file_group_descriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR); @@ -389,7 +389,7 @@ TEST_F(OSExchangeDataWinTest, TestURLExchangeFormatsViaCOM) { OSExchangeData data; std::string url_spec = "http://www.google.com/"; GURL url(url_spec); - base::string16 url_title = STRING16_LITERAL("www.google.com"); + std::u16string url_title = u"www.google.com"; data.SetURL(url, url_title); // File contents access via COM @@ -903,10 +903,10 @@ TEST_F(OSExchangeDataWinTest, VirtualFilesEmptyContents) { TEST_F(OSExchangeDataWinTest, CFHtml) { OSExchangeData data; GURL url("http://www.google.com/"); - base::string16 html( - STRING16_LITERAL("\n\n" - "bold. This is bold italic.\n" - "\n")); + std::u16string html( + u"\n\n" + u"bold. This is bold italic.\n" + u"\n"); data.SetHtml(html, url); // Check the CF_HTML too. @@ -930,18 +930,18 @@ TEST_F(OSExchangeDataWinTest, CFHtml) { TEST_F(OSExchangeDataWinTest, SetURLWithMaxPath) { OSExchangeData data; - base::string16 long_title(MAX_PATH + 1, STRING16_LITERAL('a')); + std::u16string long_title(MAX_PATH + 1, u'a'); data.SetURL(GURL("http://google.com"), long_title); } TEST_F(OSExchangeDataWinTest, ProvideURLForPlainTextURL) { OSExchangeData data; - data.SetString(STRING16_LITERAL("http://google.com")); + data.SetString(u"http://google.com"); OSExchangeData data2(data.provider().Clone()); ASSERT_TRUE(data2.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL read_url; - base::string16 title; + std::u16string title; EXPECT_TRUE(data2.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, &read_url, &title)); EXPECT_EQ(GURL("http://google.com"), read_url); diff --git a/chromium/ui/base/emoji/emoji_panel_helper.h b/chromium/ui/base/emoji/emoji_panel_helper.h index 5eb33c7bbd9..5ef9b5dde02 100644 --- a/chromium/ui/base/emoji/emoji_panel_helper.h +++ b/chromium/ui/base/emoji/emoji_panel_helper.h @@ -20,9 +20,16 @@ COMPONENT_EXPORT(UI_BASE) bool IsEmojiPanelSupported(); COMPONENT_EXPORT(UI_BASE) void ShowEmojiPanel(); #if BUILDFLAG(IS_CHROMEOS_ASH) +// Invokes the commands to show the Emoji Panel in tablet mode (ChromeOS only). +COMPONENT_EXPORT(UI_BASE) void ShowTabletModeEmojiPanel(); + // Sets a callback to show the emoji panel (ChromeOS only). COMPONENT_EXPORT(UI_BASE) void SetShowEmojiKeyboardCallback(base::RepeatingClosure callback); + +// Sets a callback to show the emoji panel in tablet mode (ChromeOS only). +COMPONENT_EXPORT(UI_BASE) +void SetTabletModeShowEmojiKeyboardCallback(base::RepeatingClosure callback); #endif } // namespace ui diff --git a/chromium/ui/base/emoji/emoji_panel_helper_chromeos.cc b/chromium/ui/base/emoji/emoji_panel_helper_chromeos.cc index e3740dd1c96..c44a29c5219 100644 --- a/chromium/ui/base/emoji/emoji_panel_helper_chromeos.cc +++ b/chromium/ui/base/emoji/emoji_panel_helper_chromeos.cc @@ -16,6 +16,11 @@ base::RepeatingClosure& GetShowEmojiKeyboardCallback() { return *callback; } +base::RepeatingClosure& GetTabletModeShowEmojiKeyboardCallback() { + static base::NoDestructor callback; + return *callback; +} + } // namespace bool IsEmojiPanelSupported() { @@ -29,8 +34,17 @@ void ShowEmojiPanel() { GetShowEmojiKeyboardCallback().Run(); } +void ShowTabletModeEmojiPanel() { + DCHECK(GetTabletModeShowEmojiKeyboardCallback()); + GetTabletModeShowEmojiKeyboardCallback().Run(); +} + void SetShowEmojiKeyboardCallback(base::RepeatingClosure callback) { GetShowEmojiKeyboardCallback() = callback; } +void SetTabletModeShowEmojiKeyboardCallback(base::RepeatingClosure callback) { + GetTabletModeShowEmojiKeyboardCallback() = callback; +} + } // namespace ui diff --git a/chromium/ui/base/glib/OWNERS b/chromium/ui/base/glib/OWNERS new file mode 100644 index 00000000000..280ba478dca --- /dev/null +++ b/chromium/ui/base/glib/OWNERS @@ -0,0 +1 @@ +thomasanderson@chromium.org diff --git a/chromium/ui/base/glib/glib_cast.h b/chromium/ui/base/glib/glib_cast.h new file mode 100644 index 00000000000..5ecf9dd46cc --- /dev/null +++ b/chromium/ui/base/glib/glib_cast.h @@ -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. + +#ifndef UI_BASE_GLIB_GLIB_CAST_H_ +#define UI_BASE_GLIB_GLIB_CAST_H_ + +#include + +#include "base/check.h" + +template +T* GlibCast(U* instance, GType g_type) { + DCHECK(G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type)); + return reinterpret_cast(instance); +} + +#endif // UI_BASE_GLIB_GLIB_CAST_H_ diff --git a/chromium/ui/base/glib/scoped_gobject.h b/chromium/ui/base/glib/scoped_gobject.h index 24ef91ec9be..7c5a5ea89bc 100644 --- a/chromium/ui/base/glib/scoped_gobject.h +++ b/chromium/ui/base/glib/scoped_gobject.h @@ -5,26 +5,33 @@ #ifndef UI_BASE_GLIB_SCOPED_GOBJECT_H_ #define UI_BASE_GLIB_SCOPED_GOBJECT_H_ -// Similar in spirit to a std::unique_ptr. +#include + +#include "base/check.h" + +// Similar to a std::shared_ptr for GObject types. template class ScopedGObject { public: - ScopedGObject() : obj_(nullptr) {} - - explicit ScopedGObject(T* obj) : obj_(obj) { Ref(); } + ScopedGObject() = default; - ScopedGObject(const ScopedGObject& other) = delete; + ScopedGObject(const ScopedGObject& other) : obj_(other.obj_) { Ref(); } ScopedGObject(ScopedGObject&& other) : obj_(other.obj_) { other.obj_ = nullptr; } - ~ScopedGObject() { reset(); } + ~ScopedGObject() { Unref(); } - ScopedGObject& operator=(const ScopedGObject& other) = delete; + ScopedGObject& operator=(const ScopedGObject& other) { + Unref(); + obj_ = other.obj_; + Ref(); + return *this; + } ScopedGObject& operator=(ScopedGObject&& other) { - reset(); + Unref(); obj_ = other.obj_; other.obj_ = nullptr; return *this; @@ -34,19 +41,27 @@ class ScopedGObject { operator T*() { return obj_; } - void reset(T* obj = nullptr) { - Unref(); - obj_ = obj; - Ref(); - } - private: - void Ref() { + template + friend ScopedGObject TakeGObject(U* obj); + template + friend ScopedGObject WrapGObject(U* obj); + + explicit ScopedGObject(T* obj) : obj_(obj) {} + + void RefSink() { // Remove the floating reference from |obj_| if it has one. if (obj_ && g_object_is_floating(obj_)) g_object_ref_sink(obj_); } + void Ref() { + if (obj_) { + DCHECK(!g_object_is_floating(obj_)); + g_object_ref(obj_); + } + } + // This function is necessary so that gtk can overload it in // the case of T = GtkStyleContext. void Unref() { @@ -54,7 +69,26 @@ class ScopedGObject { g_object_unref(obj_); } - T* obj_; + T* obj_ = nullptr; }; +// Create a ScopedGObject and do not increase the GObject's reference count. +// This is usually used to reference a newly-created GObject, which are created +// with a reference count of 1 by default. +template +ScopedGObject TakeGObject(T* obj) { + ScopedGObject scoped(obj); + scoped.RefSink(); + return scoped; +} + +// Create a ScopedGObject and increase the GObject's reference count by 1. +// This is usually used to reference an existing GObject. +template +ScopedGObject WrapGObject(T* obj) { + ScopedGObject scoped(obj); + scoped.Ref(); + return scoped; +} + #endif // UI_BASE_GLIB_SCOPED_GOBJECT_H_ diff --git a/chromium/ui/base/hit_test_x11.h b/chromium/ui/base/hit_test_x11.h index 15c41a49c31..d59a648af23 100644 --- a/chromium/ui/base/hit_test_x11.h +++ b/chromium/ui/base/hit_test_x11.h @@ -5,11 +5,13 @@ #ifndef UI_BASE_HIT_TEST_X11_H_ #define UI_BASE_HIT_TEST_X11_H_ +#include "base/component_export.h" + namespace ui { // Converts a HitTestCompat into an X11 direction recognisable by // NET_WM_MOVERESIZE event. Returns -1 if no conversion is possible. -int HitTestToWmMoveResizeDirection(int hittest); +COMPONENT_EXPORT(UI_BASE) int HitTestToWmMoveResizeDirection(int hittest); } // namespace ui diff --git a/chromium/ui/base/idle/BUILD.gn b/chromium/ui/base/idle/BUILD.gn index 2f472b5c581..73f2aebff65 100644 --- a/chromium/ui/base/idle/BUILD.gn +++ b/chromium/ui/base/idle/BUILD.gn @@ -39,6 +39,11 @@ component("idle") { sources += [ "idle_chromeos.cc" ] } + if (is_chromeos_lacros) { + sources += [ "idle_lacros.cc" ] + deps += [ "//chromeos/lacros" ] + } + if (is_mac) { sources += [ "idle_mac.mm" ] } @@ -51,7 +56,7 @@ component("idle") { sources += [ "idle_fuchsia.cc" ] } - if (is_linux || is_chromeos_lacros) { + if (is_linux) { sources += [ "idle_linux.cc" ] } diff --git a/chromium/ui/base/idle/DEPS b/chromium/ui/base/idle/DEPS index ce141545991..c0b3407624a 100644 --- a/chromium/ui/base/idle/DEPS +++ b/chromium/ui/base/idle/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+chromeos/dbus/dbus_thread_manager.h", "+chromeos/dbus/session_manager", + "+chromeos/lacros", "+ui/base/ui_base_jni_headers", ] diff --git a/chromium/ui/base/idle/idle_lacros.cc b/chromium/ui/base/idle/idle_lacros.cc new file mode 100644 index 00000000000..61a50265c7e --- /dev/null +++ b/chromium/ui/base/idle/idle_lacros.cc @@ -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. + +#include "ui/base/idle/idle.h" + +#include + +#include "chromeos/lacros/lacros_chrome_service_impl.h" +#include "chromeos/lacros/system_idle_cache.h" + +namespace ui { + +int CalculateIdleTime() { + base::TimeDelta idle_time = + base::TimeTicks::Now() - chromeos::LacrosChromeServiceImpl::Get() + ->system_idle_cache() + ->last_activity_time(); + // Clamp to positive in case of timing glitch. + return std::max(0, static_cast(idle_time.InSeconds())); +} + +bool CheckIdleStateIsLocked() { + return chromeos::LacrosChromeServiceImpl::Get() + ->system_idle_cache() + ->is_locked(); +} + +} // namespace ui diff --git a/chromium/ui/base/ime/candidate_window.h b/chromium/ui/base/ime/candidate_window.h index 3299744aeab..133f67c8f35 100644 --- a/chromium/ui/base/ime/candidate_window.h +++ b/chromium/ui/base/ime/candidate_window.h @@ -49,11 +49,11 @@ class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindow { Entry(); Entry(const Entry& other); virtual ~Entry(); - base::string16 value; - base::string16 label; - base::string16 annotation; - base::string16 description_title; - base::string16 description_body; + std::u16string value; + std::u16string label; + std::u16string annotation; + std::u16string description_title; + std::u16string description_body; }; CandidateWindow(); diff --git a/chromium/ui/base/ime/candidate_window_unittest.cc b/chromium/ui/base/ime/candidate_window_unittest.cc index 60498d4aedb..8179cb8244c 100644 --- a/chromium/ui/base/ime/candidate_window_unittest.cc +++ b/chromium/ui/base/ime/candidate_window_unittest.cc @@ -41,8 +41,8 @@ TEST(CandidateWindow, IsEqualTest) { CandidateWindow cw1; CandidateWindow cw2; - const base::string16 kSampleString1 = base::UTF8ToUTF16("Sample 1"); - const base::string16 kSampleString2 = base::UTF8ToUTF16("Sample 2"); + const std::u16string kSampleString1 = u"Sample 1"; + const std::u16string kSampleString2 = u"Sample 2"; EXPECT_TRUE(cw1.IsEqual(cw2)); EXPECT_TRUE(cw2.IsEqual(cw1)); @@ -138,7 +138,7 @@ TEST(CandidateWindow, CopyFromTest) { CandidateWindow cw1; CandidateWindow cw2; - const base::string16 kSampleString = base::UTF8ToUTF16("Sample"); + const std::u16string kSampleString = u"Sample"; cw1.set_page_size(1); cw1.set_cursor_position(2); diff --git a/chromium/ui/base/ime/character_composer.cc b/chromium/ui/base/ime/character_composer.cc index ab03a0a7c6a..891dacb5cde 100644 --- a/chromium/ui/base/ime/character_composer.cc +++ b/chromium/ui/base/ime/character_composer.cc @@ -34,7 +34,7 @@ bool CheckCharacterComposeTable( // Converts |character| to UTF16 string. // Returns false when |character| is not a valid character. -bool UTF32CharacterToUTF16(uint32_t character, base::string16* output) { +bool UTF32CharacterToUTF16(uint32_t character, std::u16string* output) { output->clear(); // Reject invalid character. (e.g. codepoint greater than 0x10ffff) if (!CBU_IS_UNICODE_CHAR(character)) @@ -157,7 +157,7 @@ bool CharacterComposer::FilterKeyPressSequenceMode(const KeyEvent& event) { bool CharacterComposer::FilterKeyPressHexMode(const KeyEvent& event) { DCHECK(composition_mode_ == HEX_MODE); const size_t kMaxHexSequenceLength = 8; - base::char16 c = event.GetCharacter(); + char16_t c = event.GetCharacter(); int hex_digit = 0; if (base::IsHexDigit(c)) { hex_digit = base::HexDigitToInt(c); diff --git a/chromium/ui/base/ime/character_composer.h b/chromium/ui/base/ime/character_composer.h index 57642c4d017..be8f1aa30d9 100644 --- a/chromium/ui/base/ime/character_composer.h +++ b/chromium/ui/base/ime/character_composer.h @@ -37,12 +37,12 @@ class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CharacterComposer { // Returns a string consisting of composed character. // Empty string is returned when there is no composition result. - const base::string16& composed_character() const { + const std::u16string& composed_character() const { return composed_character_; } // Returns the preedit string. - const base::string16& preedit_string() const { return preedit_string_; } + const std::u16string& preedit_string() const { return preedit_string_; } private: // An enum to describe composition mode. @@ -73,10 +73,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CharacterComposer { std::vector hex_buffer_; // A string representing the composed character. - base::string16 composed_character_; + std::u16string composed_character_; // Preedit string. - base::string16 preedit_string_; + std::u16string preedit_string_; // Composition mode which this instance is in. CompositionMode composition_mode_; diff --git a/chromium/ui/base/ime/character_composer_unittest.cc b/chromium/ui/base/ime/character_composer_unittest.cc index 5c4565c253e..247f509d3b6 100644 --- a/chromium/ui/base/ime/character_composer_unittest.cc +++ b/chromium/ui/base/ime/character_composer_unittest.cc @@ -26,17 +26,17 @@ namespace ui { namespace { -const base::char16 kCombiningGrave = 0x0300; -const base::char16 kCombiningAcute = 0x0301; -const base::char16 kCombiningCircumflex = 0x0302; -const base::char16 kCombiningHorn = 0x031B; +const char16_t kCombiningGrave = 0x0300; +const char16_t kCombiningAcute = 0x0301; +const char16_t kCombiningCircumflex = 0x0302; +const char16_t kCombiningHorn = 0x031B; } // namespace class CharacterComposerTest : public testing::Test { protected: // Returns a |KeyEvent| for a dead key press. - KeyEvent* DeadKeyPress(base::char16 combining_character) const { + KeyEvent* DeadKeyPress(char16_t combining_character) const { KeyEvent* event = new KeyEvent(ET_KEY_PRESSED, VKEY_UNKNOWN, DomCode::NONE, EF_NONE, DomKey::DeadKeyFromCombiningCharacter(combining_character), @@ -45,15 +45,15 @@ class CharacterComposerTest : public testing::Test { } // Expects key is filtered and no character is composed. - void ExpectDeadKeyFiltered(base::char16 combining_character) { + void ExpectDeadKeyFiltered(char16_t combining_character) { std::unique_ptr event(DeadKeyPress(combining_character)); EXPECT_TRUE(character_composer_.FilterKeyPress(*event)); EXPECT_TRUE(character_composer_.composed_character().empty()); } // Expects key is filtered and the given character is composed. - void ExpectDeadKeyComposed(base::char16 combining_character, - const base::string16& expected_character) { + void ExpectDeadKeyComposed(char16_t combining_character, + const std::u16string& expected_character) { std::unique_ptr event(DeadKeyPress(combining_character)); EXPECT_TRUE(character_composer_.FilterKeyPress(*event)); EXPECT_EQ(expected_character, character_composer_.composed_character()); @@ -63,7 +63,7 @@ class CharacterComposerTest : public testing::Test { KeyEvent* UnicodeKeyPress(KeyboardCode vkey, DomCode code, int flags, - base::char16 character) const { + char16_t character) const { KeyEvent* event = new KeyEvent(ET_KEY_PRESSED, vkey, code, flags, DomKey::FromCharacter(character), EventTimeForNow()); @@ -74,7 +74,7 @@ class CharacterComposerTest : public testing::Test { void ExpectUnicodeKeyNotFiltered(KeyboardCode vkey, DomCode code, int flags, - base::char16 character) { + char16_t character) { std::unique_ptr event( UnicodeKeyPress(vkey, code, flags, character)); EXPECT_FALSE(character_composer_.FilterKeyPress(*event)); @@ -85,7 +85,7 @@ class CharacterComposerTest : public testing::Test { void ExpectUnicodeKeyFiltered(KeyboardCode vkey, DomCode code, int flags, - base::char16 character) { + char16_t character) { std::unique_ptr event( UnicodeKeyPress(vkey, code, flags, character)); EXPECT_TRUE(character_composer_.FilterKeyPress(*event)); @@ -96,8 +96,8 @@ class CharacterComposerTest : public testing::Test { void ExpectUnicodeKeyComposed(KeyboardCode vkey, DomCode code, int flags, - base::char16 character, - const base::string16& expected_character) { + char16_t character, + const std::u16string& expected_character) { std::unique_ptr event( UnicodeKeyPress(vkey, code, flags, character)); EXPECT_TRUE(character_composer_.FilterKeyPress(*event)); @@ -136,59 +136,59 @@ TEST_F(CharacterComposerTest, FullyMatchingSequences) { // LATIN SMALL LETTER A WITH ACUTE ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x00E1)); + std::u16string(1, 0x00E1)); // LATIN CAPITAL LETTER A WITH ACUTE ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'A', - base::string16(1, 0x00C1)); + std::u16string(1, 0x00C1)); // GRAVE ACCENT ExpectDeadKeyFiltered(kCombiningGrave); - ExpectDeadKeyComposed(kCombiningGrave, base::string16(1, 0x0060)); + ExpectDeadKeyComposed(kCombiningGrave, std::u16string(1, 0x0060)); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE ExpectDeadKeyFiltered(kCombiningAcute); ExpectDeadKeyFiltered(kCombiningCircumflex); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x1EA5)); + std::u16string(1, 0x1EA5)); // LATIN CAPITAL LETTER U WITH HORN AND GRAVE ExpectDeadKeyFiltered(kCombiningGrave); ExpectDeadKeyFiltered(kCombiningHorn); ExpectUnicodeKeyComposed(VKEY_U, DomCode::US_U, EF_NONE, 'U', - base::string16(1, 0x1EEA)); + std::u16string(1, 0x1EEA)); // LATIN CAPITAL LETTER C WITH ACUTE ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_C, DomCode::US_C, EF_NONE, 'C', - base::string16(1, 0x0106)); + std::u16string(1, 0x0106)); // LATIN SMALL LETTER C WITH ACUTE ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_C, DomCode::US_C, EF_NONE, 'c', - base::string16(1, 0x0107)); + std::u16string(1, 0x0107)); // GREEK SMALL LETTER EPSILON WITH TONOS ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_E, DomCode::US_E, EF_NONE, 0x03B5, - base::string16(1, 0x03AD)); + std::u16string(1, 0x03AD)); // Windows-style sequences. // LATIN SMALL LETTER A WITH ACUTE ExpectDeadKeyFiltered('\''); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x00E1)); + std::u16string(1, 0x00E1)); // LATIN SMALL LETTER C WITH CEDILLA ExpectDeadKeyFiltered('\''); ExpectUnicodeKeyComposed(VKEY_C, DomCode::US_C, EF_NONE, 'c', - base::string16(1, 0x00E7)); + std::u16string(1, 0x00E7)); // APOSTROPHE ExpectDeadKeyFiltered('\''); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, '\'')); + std::u16string(1, '\'')); // Unmatched composition with printable character. - static constexpr base::char16 kApostropheS[] = {'\'', 's'}; + static constexpr char16_t kApostropheS[] = {'\'', 's'}; ExpectDeadKeyFiltered('\''); ExpectUnicodeKeyComposed(VKEY_S, DomCode::US_S, EF_NONE, 's', - base::string16(kApostropheS, 2)); + std::u16string(kApostropheS, 2)); // Unmatched composition with dead key. - static constexpr base::char16 kApostropheApostrophe[] = {'\'', '\''}; + static constexpr char16_t kApostropheApostrophe[] = {'\'', '\''}; ExpectDeadKeyFiltered('\''); - ExpectDeadKeyComposed('\'', base::string16(kApostropheApostrophe, 2)); + ExpectDeadKeyComposed('\'', std::u16string(kApostropheApostrophe, 2)); } TEST_F(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) { @@ -200,13 +200,13 @@ TEST_F(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) { ExpectDeadKeyFiltered(kCombiningAcute); ExpectDeadKeyFiltered(kCombiningCircumflex); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x1EA5)); + std::u16string(1, 0x1EA5)); } TEST_F(CharacterComposerTest, ComposedCharacterIsClearedAfterReset) { ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x00E1)); + std::u16string(1, 0x00E1)); character_composer_.Reset(); EXPECT_TRUE(character_composer_.composed_character().empty()); } @@ -225,7 +225,7 @@ TEST_F(CharacterComposerTest, KeySequenceCompositionPreedit) { ExpectDeadKeyFiltered(kCombiningAcute); EXPECT_TRUE(character_composer_.preedit_string().empty()); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x00E1)); + std::u16string(1, 0x00E1)); EXPECT_TRUE(character_composer_.preedit_string().empty()); } @@ -300,9 +300,9 @@ TEST_F(CharacterComposerTest, HexadecimalComposition) { ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4'); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, 0x3042)); + std::u16string(1, 0x3042)); // MUSICAL KEYBOARD (U+1F3B9) - const base::char16 kMusicalKeyboard[] = {0xd83c, 0xdfb9}; + const char16_t kMusicalKeyboard[] = {0xd83c, 0xdfb9}; ExpectUnicodeKeyFiltered(VKEY_U, DomCode::US_U, EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U'); ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, EF_NONE, '1'); @@ -312,7 +312,7 @@ TEST_F(CharacterComposerTest, HexadecimalComposition) { ExpectUnicodeKeyFiltered(VKEY_9, DomCode::DIGIT9, EF_NONE, '9'); ExpectUnicodeKeyComposed( VKEY_RETURN, DomCode::ENTER, EF_NONE, '\r', - base::string16(kMusicalKeyboard, + std::u16string(kMusicalKeyboard, kMusicalKeyboard + base::size(kMusicalKeyboard))); } @@ -320,38 +320,38 @@ TEST_F(CharacterComposerTest, HexadecimalCompositionPreedit) { // HIRAGANA LETTER A (U+3042) ExpectUnicodeKeyFiltered(VKEY_U, DomCode::US_U, EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U'); - EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string()); + EXPECT_EQ(u"u", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, 0, '3'); - EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0'); - EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string()); + EXPECT_EQ(u"u30", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, 0, '4'); - EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_A, DomCode::US_A, 0, 'a'); - EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304a", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_BACK, DomCode::BACKSPACE, EF_NONE, '\b'); - EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_RETURN, DomCode::ENTER, EF_NONE, '\r', - base::string16(1, 0x3042)); - EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string()); + std::u16string(1, 0x3042)); + EXPECT_EQ(u"", character_composer_.preedit_string()); // Sequence with an ignored character ('x') and Escape. ExpectUnicodeKeyFiltered(VKEY_U, DomCode::US_U, EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U'); - EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string()); + EXPECT_EQ(u"u", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, 0, '3'); - EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0'); - EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string()); + EXPECT_EQ(u"u30", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_X, DomCode::US_X, 0, 'x'); - EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string()); + EXPECT_EQ(u"u30", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, 0, '4'); - EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, 0, '2'); - EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3042", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(VKEY_ESCAPE, DomCode::ESCAPE, EF_NONE, 0x1B); - EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string()); + EXPECT_EQ(u"", character_composer_.preedit_string()); } TEST_F(CharacterComposerTest, HexadecimalCompositionWithNonHexKey) { @@ -371,7 +371,7 @@ TEST_F(CharacterComposerTest, HexadecimalCompositionWithNonHexKey) { ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4'); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, 0x3042)); + std::u16string(1, 0x3042)); } TEST_F(CharacterComposerTest, HexadecimalCompositionWithAdditionalModifiers) { @@ -384,7 +384,7 @@ TEST_F(CharacterComposerTest, HexadecimalCompositionWithAdditionalModifiers) { ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4'); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, 0x3042)); + std::u16string(1, 0x3042)); // Ctrl+Shift+u (CapsLock enabled) ExpectUnicodeKeyNotFiltered(VKEY_U, DomCode::US_U, @@ -409,7 +409,7 @@ TEST_F(CharacterComposerTest, CancelHexadecimalComposition) { ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4'); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, 0x3042)); + std::u16string(1, 0x3042)); } TEST_F(CharacterComposerTest, HexadecimalCompositionWithBackspace) { @@ -423,7 +423,7 @@ TEST_F(CharacterComposerTest, HexadecimalCompositionWithBackspace) { ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4'); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, 0x3042)); + std::u16string(1, 0x3042)); } TEST_F(CharacterComposerTest, CancelHexadecimalCompositionWithBackspace) { @@ -448,40 +448,40 @@ TEST_F(CharacterComposerTest, const int kControlShift = EF_CONTROL_DOWN | EF_SHIFT_DOWN; // HIRAGANA LETTER A (U+3042) ExpectUnicodeKeyFiltered(ui::VKEY_U, DomCode::US_U, kControlShift, 0x15); - EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string()); + EXPECT_EQ(u"u", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_3, DomCode::DIGIT3, kControlShift, '#'); - EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_0, DomCode::DIGIT0, kControlShift, ')'); - EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string()); + EXPECT_EQ(u"u30", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_4, DomCode::DIGIT4, kControlShift, '$'); - EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_A, DomCode::US_A, kControlShift, 0x01); - EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304a", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_BACK, DomCode::BACKSPACE, kControlShift, '\b'); - EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_2, DomCode::DIGIT2, kControlShift, 0); - EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3042", character_composer_.preedit_string()); ExpectUnicodeKeyComposed(VKEY_RETURN, DomCode::ENTER, kControlShift, '\r', - base::string16(1, 0x3042)); - EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string()); + std::u16string(1, 0x3042)); + EXPECT_EQ(u"", character_composer_.preedit_string()); // Sequence with an ignored character (control + shift + 'x') and Escape. ExpectUnicodeKeyFiltered(ui::VKEY_U, DomCode::US_U, kControlShift, 'U'); - EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string()); + EXPECT_EQ(u"u", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_3, DomCode::DIGIT3, kControlShift, '#'); - EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_0, DomCode::DIGIT0, kControlShift, ')'); - EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string()); + EXPECT_EQ(u"u30", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_X, DomCode::US_X, kControlShift, 'X'); - EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string()); + EXPECT_EQ(u"u30", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_4, DomCode::DIGIT4, kControlShift, '$'); - EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string()); + EXPECT_EQ(u"u304", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_2, DomCode::DIGIT2, kControlShift, 0); - EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_.preedit_string()); + EXPECT_EQ(u"u3042", character_composer_.preedit_string()); ExpectUnicodeKeyFiltered(ui::VKEY_ESCAPE, DomCode::ESCAPE, kControlShift, 0x1B); - EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string()); + EXPECT_EQ(u"", character_composer_.preedit_string()); } TEST_F(CharacterComposerTest, InvalidHexadecimalSequence) { @@ -523,7 +523,7 @@ TEST_F(CharacterComposerTest, HexadecimalSequenceAndDeadKey) { // LATIN SMALL LETTER A WITH ACUTE ExpectDeadKeyFiltered(kCombiningAcute); ExpectUnicodeKeyComposed(VKEY_A, DomCode::US_A, EF_NONE, 'a', - base::string16(1, 0x00E1)); + std::u16string(1, 0x00E1)); // HIRAGANA LETTER A (U+3042) with dead_acute ignored. ExpectUnicodeKeyFiltered(VKEY_U, DomCode::US_U, EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15); @@ -533,7 +533,7 @@ TEST_F(CharacterComposerTest, HexadecimalSequenceAndDeadKey) { ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4'); ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2'); ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ', - base::string16(1, 0x3042)); + std::u16string(1, 0x3042)); } } // namespace ui diff --git a/chromium/ui/base/ime/composition_text.cc b/chromium/ui/base/ime/composition_text.cc index ab2136e9d1e..1544a3ef7af 100644 --- a/chromium/ui/base/ime/composition_text.cc +++ b/chromium/ui/base/ime/composition_text.cc @@ -6,12 +6,19 @@ namespace ui { -CompositionText::CompositionText() { -} +CompositionText::CompositionText() = default; CompositionText::CompositionText(const CompositionText& other) = default; -CompositionText::~CompositionText() { +CompositionText::~CompositionText() = default; + +bool CompositionText::operator==(const CompositionText& other) const { + return text == other.text && ime_text_spans == other.ime_text_spans && + selection == other.selection; +} + +bool CompositionText::operator!=(const CompositionText& other) const { + return !(*this == other); } } // namespace ui diff --git a/chromium/ui/base/ime/composition_text.h b/chromium/ui/base/ime/composition_text.h index cddf445ec1f..ee047edd576 100644 --- a/chromium/ui/base/ime/composition_text.h +++ b/chromium/ui/base/ime/composition_text.h @@ -7,8 +7,9 @@ #include +#include + #include "base/component_export.h" -#include "base/strings/string16.h" #include "ui/base/ime/ime_text_span.h" #include "ui/gfx/range/range.h" @@ -20,23 +21,11 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CompositionText { CompositionText(const CompositionText& other); ~CompositionText(); - bool operator==(const CompositionText& rhs) const { - if ((this->text != rhs.text) || (this->selection != rhs.selection) || - (this->ime_text_spans.size() != rhs.ime_text_spans.size())) - return false; - for (size_t i = 0; i < this->ime_text_spans.size(); ++i) { - if (this->ime_text_spans[i] != rhs.ime_text_spans[i]) - return false; - } - return true; - } - - bool operator!=(const CompositionText& rhs) const { - return !(*this == rhs); - } + bool operator==(const CompositionText& other) const; + bool operator!=(const CompositionText& other) const; // Content of the composition text. - base::string16 text; + std::u16string text; // ImeTextSpan information for the composition text. ImeTextSpans ime_text_spans; diff --git a/chromium/ui/base/ime/composition_text_unittest.cc b/chromium/ui/base/ime/composition_text_unittest.cc index 991a71f5cd5..95ccec47b6f 100644 --- a/chromium/ui/base/ime/composition_text_unittest.cc +++ b/chromium/ui/base/ime/composition_text_unittest.cc @@ -12,7 +12,7 @@ namespace ui { TEST(CompositionTextTest, CopyTest) { - const base::string16 kSampleText = base::UTF8ToUTF16("Sample Text"); + const std::u16string kSampleText = u"Sample Text"; const ImeTextSpan kSampleUnderline1( ImeTextSpan::Type::kComposition, 10, 20, ImeTextSpan::Thickness::kThin, ImeTextSpan::UnderlineStyle::kSolid, SK_ColorTRANSPARENT); diff --git a/chromium/ui/base/ime/dummy_input_method.cc b/chromium/ui/base/ime/dummy_input_method.cc index f1f7a2f2322..50f6be85e29 100644 --- a/chromium/ui/base/ime/dummy_input_method.cc +++ b/chromium/ui/base/ime/dummy_input_method.cc @@ -28,6 +28,12 @@ bool DummyInputMethod::OnUntranslatedIMEMessage(const MSG event, NativeEventResult* result) { return false; } + +void DummyInputMethod::OnInputLocaleChanged() {} + +bool DummyInputMethod::IsInputLocaleCJK() const { + return false; +} #endif void DummyInputMethod::SetFocusedTextInputClient(TextInputClient* client) { @@ -54,13 +60,6 @@ void DummyInputMethod::OnCaretBoundsChanged(const TextInputClient* client) { void DummyInputMethod::CancelComposition(const TextInputClient* client) { } -void DummyInputMethod::OnInputLocaleChanged() { -} - -bool DummyInputMethod::IsInputLocaleCJK() const { - return false; -} - TextInputType DummyInputMethod::GetTextInputType() const { return TEXT_INPUT_TYPE_NONE; } diff --git a/chromium/ui/base/ime/dummy_input_method.h b/chromium/ui/base/ime/dummy_input_method.h index 35536b61970..f403e5f0bb4 100644 --- a/chromium/ui/base/ime/dummy_input_method.h +++ b/chromium/ui/base/ime/dummy_input_method.h @@ -26,6 +26,8 @@ class DummyInputMethod : public InputMethod { #if defined(OS_WIN) bool OnUntranslatedIMEMessage(const MSG event, NativeEventResult* result) override; + void OnInputLocaleChanged() override; + bool IsInputLocaleCJK() const override; #endif void SetFocusedTextInputClient(TextInputClient* client) override; @@ -35,8 +37,6 @@ class DummyInputMethod : public InputMethod { void OnTextInputTypeChanged(const TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; - void OnInputLocaleChanged() override; - bool IsInputLocaleCJK() const override; TextInputType GetTextInputType() const override; TextInputMode GetTextInputMode() const override; int GetTextInputFlags() const override; diff --git a/chromium/ui/base/ime/dummy_text_input_client.cc b/chromium/ui/base/ime/dummy_text_input_client.cc index 38114a428c2..d063f39d801 100644 --- a/chromium/ui/base/ime/dummy_text_input_client.cc +++ b/chromium/ui/base/ime/dummy_text_input_client.cc @@ -45,7 +45,7 @@ void DummyTextInputClient::ClearCompositionText() { } void DummyTextInputClient::InsertText( - const base::string16& text, + const std::u16string& text, InsertTextCursorBehavior cursor_behavior) { insert_text_history_.push_back(text); } @@ -115,7 +115,7 @@ bool DummyTextInputClient::DeleteRange(const gfx::Range& range) { } bool DummyTextInputClient::GetTextFromRange(const gfx::Range& range, - base::string16* text) const { + std::u16string* text) const { return false; } @@ -180,7 +180,7 @@ void DummyTextInputClient::GetActiveTextInputControlLayoutBounds( void DummyTextInputClient::SetActiveCompositionForAccessibility( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed) {} #endif diff --git a/chromium/ui/base/ime/dummy_text_input_client.h b/chromium/ui/base/ime/dummy_text_input_client.h index d686a4741d3..7908a32d38c 100644 --- a/chromium/ui/base/ime/dummy_text_input_client.h +++ b/chromium/ui/base/ime/dummy_text_input_client.h @@ -29,7 +29,7 @@ class DummyTextInputClient : public TextInputClient { void SetCompositionText(const CompositionText& composition) override; uint32_t ConfirmCompositionText(bool keep_selection) override; void ClearCompositionText() override; - void InsertText(const base::string16& text, + void InsertText(const std::u16string& text, InsertTextCursorBehavior cursor_behavior) override; void InsertChar(const KeyEvent& event) override; TextInputType GetTextInputType() const override; @@ -48,7 +48,7 @@ class DummyTextInputClient : public TextInputClient { bool SetEditableSelectionRange(const gfx::Range& range) override; bool DeleteRange(const gfx::Range& range) override; bool GetTextFromRange(const gfx::Range& range, - base::string16* text) const override; + std::u16string* text) const override; void OnInputMethodChanged() override; bool ChangeTextDirectionAndLayoutAlignment( base::i18n::TextDirection direction) override; @@ -77,13 +77,13 @@ class DummyTextInputClient : public TextInputClient { base::Optional* selection_bounds) override; void SetActiveCompositionForAccessibility( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed) override; #endif int insert_char_count() const { return insert_char_count_; } - base::char16 last_insert_char() const { return last_insert_char_; } - const std::vector& insert_text_history() const { + char16_t last_insert_char() const { return last_insert_char_; } + const std::vector& insert_text_history() const { return insert_text_history_; } const std::vector& composition_history() const { @@ -100,8 +100,8 @@ class DummyTextInputClient : public TextInputClient { private: int insert_char_count_; - base::char16 last_insert_char_; - std::vector insert_text_history_; + char16_t last_insert_char_; + std::vector insert_text_history_; std::vector composition_history_; std::vector selection_history_; gfx::Range autocorrect_range_; diff --git a/chromium/ui/base/ime/fake_text_input_client.cc b/chromium/ui/base/ime/fake_text_input_client.cc index 647dbec8a0f..4932bc8d6e2 100644 --- a/chromium/ui/base/ime/fake_text_input_client.cc +++ b/chromium/ui/base/ime/fake_text_input_client.cc @@ -20,7 +20,7 @@ void FakeTextInputClient::set_text_input_type(TextInputType text_input_type) { text_input_type_ = text_input_type; } -void FakeTextInputClient::SetTextAndSelection(const base::string16& text, +void FakeTextInputClient::SetTextAndSelection(const std::u16string& text, gfx::Range selection) { DCHECK_LE(selection_.end(), text.length()); text_ = text; @@ -37,9 +37,14 @@ uint32_t FakeTextInputClient::ConfirmCompositionText(bool keep_selection) { void FakeTextInputClient::ClearCompositionText() {} void FakeTextInputClient::InsertText( - const base::string16& text, + const std::u16string& text, TextInputClient::InsertTextCursorBehavior cursor_behavior) { - text_.insert(selection_.start(), text); + if (!composition_range_.is_empty()) { + text_.replace(composition_range_.start(), composition_range_.length(), + text); + } else { + text_.replace(selection_.start(), selection_.length(), text); + } if (cursor_behavior == TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText) { @@ -80,7 +85,7 @@ bool FakeTextInputClient::GetCompositionCharacterBounds(uint32_t index, } bool FakeTextInputClient::HasCompositionText() const { - return false; + return !composition_range_.is_empty(); } ui::TextInputClient::FocusReason FakeTextInputClient::GetFocusReason() const { @@ -110,7 +115,7 @@ bool FakeTextInputClient::DeleteRange(const gfx::Range& range) { } bool FakeTextInputClient::GetTextFromRange(const gfx::Range& range, - base::string16* text) const { + std::u16string* text) const { return false; } @@ -157,7 +162,7 @@ bool FakeTextInputClient::SetCompositionFromExistingText( #if BUILDFLAG(IS_CHROMEOS_ASH) gfx::Range FakeTextInputClient::GetAutocorrectRange() const { - return {}; + return autocorrect_range_; } gfx::Rect FakeTextInputClient::GetAutocorrectCharacterBounds() const { @@ -165,7 +170,8 @@ gfx::Rect FakeTextInputClient::GetAutocorrectCharacterBounds() const { } bool FakeTextInputClient::SetAutocorrectRange(const gfx::Range& range) { - return false; + autocorrect_range_ = range; + return true; } #endif @@ -176,7 +182,7 @@ void FakeTextInputClient::GetActiveTextInputControlLayoutBounds( void FakeTextInputClient::SetActiveCompositionForAccessibility( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed) {} #endif diff --git a/chromium/ui/base/ime/fake_text_input_client.h b/chromium/ui/base/ime/fake_text_input_client.h index fbf2c6bd532..d282ea58760 100644 --- a/chromium/ui/base/ime/fake_text_input_client.h +++ b/chromium/ui/base/ime/fake_text_input_client.h @@ -25,9 +25,9 @@ class FakeTextInputClient : public TextInputClient { ~FakeTextInputClient() override; void set_text_input_type(TextInputType text_input_type); - void SetTextAndSelection(const base::string16& text, gfx::Range selection); + void SetTextAndSelection(const std::u16string& text, gfx::Range selection); - const base::string16& text() const { return text_; } + const std::u16string& text() const { return text_; } const gfx::Range& selection() const { return selection_; } const gfx::Range& composition_range() const { return composition_range_; } const std::vector& ime_text_spans() const { @@ -39,7 +39,7 @@ class FakeTextInputClient : public TextInputClient { uint32_t ConfirmCompositionText(bool keep_selection) override; void ClearCompositionText() override; void InsertText( - const base::string16& text, + const std::u16string& text, TextInputClient::InsertTextCursorBehavior cursor_behavior) override; void InsertChar(const KeyEvent& event) override; TextInputType GetTextInputType() const override; @@ -58,7 +58,7 @@ class FakeTextInputClient : public TextInputClient { bool SetEditableSelectionRange(const gfx::Range& range) override; bool DeleteRange(const gfx::Range& range) override; bool GetTextFromRange(const gfx::Range& range, - base::string16* text) const override; + std::u16string* text) const override; void OnInputMethodChanged() override; bool ChangeTextDirectionAndLayoutAlignment( base::i18n::TextDirection direction) override; @@ -84,16 +84,17 @@ class FakeTextInputClient : public TextInputClient { base::Optional* selection_bounds) override; void SetActiveCompositionForAccessibility( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed) override; #endif private: TextInputType text_input_type_; - base::string16 text_; + std::u16string text_; gfx::Range selection_; gfx::Range composition_range_; std::vector ime_text_spans_; + gfx::Range autocorrect_range_; }; } // namespace ui diff --git a/chromium/ui/base/ime/fuchsia/BUILD.gn b/chromium/ui/base/ime/fuchsia/BUILD.gn index e4a1e8ece6d..1b98ae14b06 100644 --- a/chromium/ui/base/ime/fuchsia/BUILD.gn +++ b/chromium/ui/base/ime/fuchsia/BUILD.gn @@ -10,6 +10,8 @@ component("fuchsia") { sources = [ "input_method_fuchsia.cc", "input_method_fuchsia.h", + "keyboard_client.cc", + "keyboard_client.h", "virtual_keyboard_controller_fuchsia.cc", "virtual_keyboard_controller_fuchsia.h", ] @@ -17,7 +19,9 @@ component("fuchsia") { defines = [ "IS_UI_BASE_IME_FUCHSIA_IMPL" ] public_deps = [ + "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.input.virtualkeyboard", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input", + "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input3", "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp", "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp", "//ui/base/ime", diff --git a/chromium/ui/base/ime/fuchsia/OWNERS b/chromium/ui/base/ime/fuchsia/OWNERS new file mode 100644 index 00000000000..e7034eabb1e --- /dev/null +++ b/chromium/ui/base/ime/fuchsia/OWNERS @@ -0,0 +1 @@ +file://build/fuchsia/OWNERS diff --git a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc index 5b6b97dde06..aaa5a1e142c 100644 --- a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc +++ b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc @@ -20,12 +20,7 @@ namespace ui { InputMethodFuchsia::InputMethodFuchsia(internal::InputMethodDelegate* delegate, fuchsia::ui::views::ViewRef view_ref) : InputMethodBase(delegate), - event_converter_(this), - ime_client_binding_(this), - ime_service_(base::ComponentContextForProcess() - ->svc() - ->Connect()), - virtual_keyboard_controller_(ime_service_.get()) {} + virtual_keyboard_controller_(std::move(view_ref), this) {} InputMethodFuchsia::~InputMethodFuchsia() {} @@ -33,11 +28,6 @@ VirtualKeyboardController* InputMethodFuchsia::GetVirtualKeyboardController() { return &virtual_keyboard_controller_; } -void InputMethodFuchsia::DispatchEvent(ui::Event* event) { - DCHECK(event->IsKeyEvent()); - DispatchKeyEvent(event->AsKeyEvent()); -} - ui::EventDispatchDetails InputMethodFuchsia::DispatchKeyEvent( ui::KeyEvent* event) { DCHECK(event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED); @@ -67,53 +57,4 @@ bool InputMethodFuchsia::IsCandidatePopupOpen() const { return false; } -void InputMethodFuchsia::OnFocus() { - DCHECK(!ime_); - - // TODO(crbug.com/876934): Instantiate the IME with details about the text - // being edited. - fuchsia::ui::input::TextInputState state = {}; - state.text = ""; - ime_service_->GetInputMethodEditor( - fuchsia::ui::input::KeyboardType::TEXT, - fuchsia::ui::input::InputMethodAction::UNSPECIFIED, std::move(state), - ime_client_binding_.NewBinding(), ime_.NewRequest()); -} - -void InputMethodFuchsia::OnBlur() { - virtual_keyboard_controller_.DismissVirtualKeyboard(); - ime_client_binding_.Unbind(); - ime_.Unbind(); -} - -void InputMethodFuchsia::DidUpdateState( - fuchsia::ui::input::TextInputState state, - std::unique_ptr input_event) { - // The FIDL protocol for DidUpdateState allows it to be null, and so we may - // receive state updates that have no associated key. Since we're only - // interested in extracting out input events from this stream for now, we can - // just ignore state updates with no input event. - if (!input_event) - return; - - if (input_event->is_keyboard()) - event_converter_.ProcessEvent(*input_event); - else - NOTIMPLEMENTED(); -} - -void InputMethodFuchsia::OnAction( - fuchsia::ui::input::InputMethodAction action) { - if (action != fuchsia::ui::input::InputMethodAction::UNSPECIFIED) { - NOTIMPLEMENTED(); - return; - } - - // Synthesize an ENTER keypress and send it to the Window. - KeyEvent key_event(ET_KEY_PRESSED, KeyboardCode::VKEY_RETURN, - ui::DomCode::ENTER, ui::EF_NONE, ui::DomKey::ENTER, - ui::EventTimeForNow()); - DispatchKeyEvent(&key_event); -} - } // namespace ui diff --git a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h index 52aa48db4e7..511f2c9ea7f 100644 --- a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h +++ b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.h @@ -16,61 +16,31 @@ #include "ui/base/ime/input_method_base.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/events/fuchsia/input_event_dispatcher.h" -#include "ui/events/fuchsia/input_event_dispatcher_delegate.h" +#include "ui/events/fuchsia/input_event_sink.h" #include "ui/gfx/native_widget_types.h" namespace ui { // Handles input from physical keyboards and the IME service. class COMPONENT_EXPORT(UI_BASE_IME_FUCHSIA) InputMethodFuchsia - : public InputMethodBase, - public InputEventDispatcherDelegate, - public fuchsia::ui::input::InputMethodEditorClient { + : public InputMethodBase { public: InputMethodFuchsia(internal::InputMethodDelegate* delegate, fuchsia::ui::views::ViewRef view_ref); ~InputMethodFuchsia() override; - fuchsia::ui::input::ImeService* ime_service() const { - return ime_service_.get(); - } + InputMethodFuchsia(InputMethodFuchsia&) = delete; + InputMethodFuchsia operator=(InputMethodFuchsia&) = delete; // InputMethodBase interface implementation. - VirtualKeyboardController* GetVirtualKeyboardController() override; - ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; - void OnCaretBoundsChanged(const TextInputClient* client) override; - void CancelComposition(const TextInputClient* client) override; - bool IsCandidatePopupOpen() const override; - void OnFocus() override; - void OnBlur() override; + VirtualKeyboardController* GetVirtualKeyboardController() final; + ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) final; + void OnCaretBoundsChanged(const TextInputClient* client) final; + void CancelComposition(const TextInputClient* client) final; + bool IsCandidatePopupOpen() const final; private: - // Establishes a connection to the input service and starts receiving input - // events from hard and soft keyboards. - void ConnectInputService(); - - // Terminates the connection to the input services, which stops receiving - // input events. - void DisconnectInputService(); - - // InputEventDispatcherDelegate interface implementation. - void DispatchEvent(ui::Event* event) override; - - // InputMethodEditorClient interface implementation. - void DidUpdateState( - fuchsia::ui::input::TextInputState state, - std::unique_ptr input_event) override; - void OnAction(fuchsia::ui::input::InputMethodAction action) override; - - InputEventDispatcher event_converter_; - fidl::Binding - ime_client_binding_; - fuchsia::ui::input::ImeServicePtr ime_service_; - fuchsia::ui::input::InputMethodEditorPtr ime_; - fuchsia::ui::input::ImeVisibilityServicePtr ime_visibility_; VirtualKeyboardControllerFuchsia virtual_keyboard_controller_; - - DISALLOW_COPY_AND_ASSIGN(InputMethodFuchsia); }; } // namespace ui diff --git a/chromium/ui/base/ime/fuchsia/keyboard_client.cc b/chromium/ui/base/ime/fuchsia/keyboard_client.cc new file mode 100644 index 00000000000..ab9fc10fbc2 --- /dev/null +++ b/chromium/ui/base/ime/fuchsia/keyboard_client.cc @@ -0,0 +1,167 @@ +// 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/ime/fuchsia/keyboard_client.h" +#include + +#include "base/logging.h" +#include "base/notreached.h" +#include "ui/events/fuchsia/input_event_sink.h" +#include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" + +namespace ui { + +namespace { + +// Converts the state of modifiers managed by Fuchsia (e.g. Caps and Num Lock) +// into ui::Event flags. +int ModifiersToEventFlags(const fuchsia::ui::input3::Modifiers& modifiers) { + int event_flags = 0; + if ((modifiers & fuchsia::ui::input3::Modifiers::CAPS_LOCK) == + fuchsia::ui::input3::Modifiers::CAPS_LOCK) { + event_flags |= EF_CAPS_LOCK_ON; + } + if ((modifiers & fuchsia::ui::input3::Modifiers::NUM_LOCK) == + fuchsia::ui::input3::Modifiers::NUM_LOCK) { + event_flags |= EF_NUM_LOCK_ON; + } + if ((modifiers & fuchsia::ui::input3::Modifiers::SCROLL_LOCK) == + fuchsia::ui::input3::Modifiers::SCROLL_LOCK) { + event_flags |= EF_SCROLL_LOCK_ON; + } + return event_flags; +} + +} // namespace + +KeyboardClient::KeyboardClient(fuchsia::ui::input3::Keyboard* keyboard_service, + fuchsia::ui::views::ViewRef view_ref, + InputEventSink* event_sink) + : binding_(this), event_sink_(event_sink) { + DCHECK(event_sink_); + + // Connect to the Keyboard service and register |keyboard_client_| as a + // listener. + fidl::InterfaceHandle + keyboard_listener; + fidl::InterfaceRequest + keyboard_listener_request = keyboard_listener.NewRequest(); + keyboard_service->AddListener(std::move(view_ref), + std::move(keyboard_listener), [] {}); + binding_.Bind(std::move(keyboard_listener_request)); +} + +KeyboardClient::~KeyboardClient() = default; + +void KeyboardClient::OnKeyEvent( + fuchsia::ui::input3::KeyEvent key_event, + fuchsia::ui::input3::KeyboardListener::OnKeyEventCallback callback) { + if (ProcessKeyEvent(key_event)) { + callback(fuchsia::ui::input3::KeyEventStatus::HANDLED); + } else { + callback(fuchsia::ui::input3::KeyEventStatus::NOT_HANDLED); + } +} + +bool KeyboardClient::ProcessKeyEvent( + const fuchsia::ui::input3::KeyEvent& key_event) { + if (!key_event.has_type() || !key_event.has_key() || + !key_event.has_timestamp()) { + LOG(ERROR) << "Could not process incomplete input3::KeyEvent."; + return false; + } + + // Update activation flags of modifier keys (SHIFT, ALT, etc). This needs to + // be done for all key event types. + UpdatedCachedModifiers(key_event); + + EventType event_type; + switch (key_event.type()) { + case fuchsia::ui::input3::KeyEventType::PRESSED: + event_type = ET_KEY_PRESSED; + break; + case fuchsia::ui::input3::KeyEventType::RELEASED: + event_type = ET_KEY_RELEASED; + break; + case fuchsia::ui::input3::KeyEventType::SYNC: + case fuchsia::ui::input3::KeyEventType::CANCEL: + // SYNC and CANCEL should not generate ui::Events. + return true; + default: + NOTIMPLEMENTED() << "Unknown KeyEventType received: " + << static_cast(event_type); + return false; + } + + // Convert |key_event| to a ui::KeyEvent. + DomCode dom_code = + KeycodeConverter::UsbKeycodeToDomCode(static_cast(key_event.key())); + int event_flags = EventFlagsForCachedModifiers(); + if (key_event.has_modifiers()) + event_flags |= ModifiersToEventFlags(key_event.modifiers()); + + // TODO(https://crbug.com/1187257): Use input3.KeyMeaning instead of US layout + // as the default. + DomKey dom_key; + KeyboardCode key_code; + if (!DomCodeToUsLayoutDomKey(dom_code, event_flags, &dom_key, &key_code)) { + LOG(ERROR) << "DomCodeToUsLayoutDomKey() failed for key: " + << static_cast(key_event.key()); + } + + ui::KeyEvent ui_key_event(event_type, key_code, dom_code, event_flags, + dom_key, + base::TimeTicks::FromZxTime(key_event.timestamp())); + event_sink_->DispatchEvent(&ui_key_event); + return ui_key_event.handled(); +} + +// TODO(https://crbug.com/850697): Add additional modifiers as they become +// supported. +void KeyboardClient::UpdatedCachedModifiers( + const fuchsia::ui::input3::KeyEvent& key_event) { + // A SYNC event indicates that the key was pressed while the view gained input + // focus. A CANCEL event indicates the key was held when the view lost input + // focus. In both cases, the state of locally tracked modifiers should be + // updated. + bool modifier_active = + key_event.type() == fuchsia::ui::input3::KeyEventType::PRESSED || + key_event.type() == fuchsia::ui::input3::KeyEventType::SYNC; + switch (key_event.key()) { + case fuchsia::input::Key::LEFT_SHIFT: + left_shift_ = modifier_active; + break; + case fuchsia::input::Key::RIGHT_SHIFT: + right_shift_ = modifier_active; + break; + case fuchsia::input::Key::LEFT_ALT: + left_alt_ = modifier_active; + break; + case fuchsia::input::Key::RIGHT_ALT: + right_alt_ = modifier_active; + break; + case fuchsia::input::Key::LEFT_CTRL: + left_ctrl_ = modifier_active; + break; + case fuchsia::input::Key::RIGHT_CTRL: + right_ctrl_ = modifier_active; + break; + default: + break; + } +} + +int KeyboardClient::EventFlagsForCachedModifiers() { + int event_flags = 0; + if (left_shift_ || right_shift_) + event_flags |= EF_SHIFT_DOWN; + if (left_alt_ || right_alt_) + event_flags |= EF_ALT_DOWN; + if (left_ctrl_ || right_ctrl_) + event_flags |= EF_CONTROL_DOWN; + return event_flags; +} + +} // namespace ui diff --git a/chromium/ui/base/ime/fuchsia/keyboard_client.h b/chromium/ui/base/ime/fuchsia/keyboard_client.h new file mode 100644 index 00000000000..d74aeb07309 --- /dev/null +++ b/chromium/ui/base/ime/fuchsia/keyboard_client.h @@ -0,0 +1,69 @@ +// 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_IME_FUCHSIA_KEYBOARD_CLIENT_H_ +#define UI_BASE_IME_FUCHSIA_KEYBOARD_CLIENT_H_ + +#include +#include +#include + +#include "base/component_export.h" +#include "ui/events/event.h" + +namespace ui { + +class InputEventSink; + +// Handles keyboard events from the Fuchsia keyboard service. +class COMPONENT_EXPORT(UI_BASE_IME_FUCHSIA) KeyboardClient + : public fuchsia::ui::input3::KeyboardListener { + public: + // |keyboard_service| and |event_sink| must outlive |this|. + KeyboardClient(fuchsia::ui::input3::Keyboard* keyboard_service, + fuchsia::ui::views::ViewRef view_ref, + InputEventSink* event_sink); + ~KeyboardClient() override; + + KeyboardClient(const KeyboardClient&) = delete; + KeyboardClient& operator=(const KeyboardClient&) = delete; + + // fuchsia::ui::input3::KeyboardListener implementation. + void OnKeyEvent( + fuchsia::ui::input3::KeyEvent key_event, + fuchsia::ui::input3::KeyboardListener::OnKeyEventCallback callback) final; + + private: + // Handles converting and propagating |key_event|. Returns false if critical + // information about |key_event| is missing, or if the key's event type is not + // supported. + // TODO(http://fxbug.dev/69620): Add support for SYNC and CANCEL key event + // types. + bool ProcessKeyEvent(const fuchsia::ui::input3::KeyEvent& key_event); + + // Update the value of modifiers such as shift. + void UpdatedCachedModifiers(const fuchsia::ui::input3::KeyEvent& key_event); + + // Translate state of locally tracked modifier keys (e.g. shift, alt) into + // ui::Event flags. + int EventFlagsForCachedModifiers(); + + fidl::Binding binding_; + + // Dispatches events into Chromium once they have been converted to + // ui::KeyEvents. + InputEventSink* event_sink_; + + // Tracks the activation state of the named modifier keys. + bool left_shift_ = false; + bool right_shift_ = false; + bool left_alt_ = false; + bool right_alt_ = false; + bool left_ctrl_ = false; + bool right_ctrl_ = false; +}; + +} // namespace ui + +#endif // UI_BASE_IME_FUCHSIA_KEYBOARD_CLIENT_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 f5d113048c2..70031994afe 100644 --- a/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc +++ b/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.cc @@ -4,57 +4,104 @@ #include "ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h" +#include #include #include #include "base/check.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/process_context.h" -#include "base/notreached.h" 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( - fuchsia::ui::input::ImeService* ime_service) - : ime_service_(ime_service), - ime_visibility_( - base::ComponentContextForProcess() - ->svc() - ->Connect()) { - DCHECK(ime_service_); - - ime_visibility_.set_error_handler([](zx_status_t status) { - ZX_LOG(FATAL, status) << " ImeVisibilityService lost."; + fuchsia::ui::views::ViewRef view_ref, + ui::InputMethodBase* input_method) + : input_method_(input_method) { + DCHECK(input_method_); + + base::ComponentContextForProcess() + ->svc() + ->Connect() + ->Create(std::move(view_ref), + ConvertTextInputMode(input_method_->GetTextInputMode()), + controller_service_.NewRequest()); + + controller_service_.set_error_handler([this](zx_status_t status) { + ZX_LOG(ERROR, status) << "virtualkeyboard::Controller disconnected"; + keyboard_visible_ = false; }); - ime_visibility_.events().OnKeyboardVisibilityChanged = [this](bool visible) { - keyboard_visible_ = visible; - }; + WatchVisibility(); } VirtualKeyboardControllerFuchsia::~VirtualKeyboardControllerFuchsia() = default; bool VirtualKeyboardControllerFuchsia::DisplayVirtualKeyboard() { - ime_service_->ShowKeyboard(); + if (!controller_service_) + return false; + + controller_service_->SetTextType( + ConvertTextInputMode(input_method_->GetTextInputMode())); + + if (!keyboard_visible_) + controller_service_->RequestShow(); + return true; } void VirtualKeyboardControllerFuchsia::DismissVirtualKeyboard() { - ime_service_->HideKeyboard(); + if (!controller_service_) + return; + + controller_service_->RequestHide(); } void VirtualKeyboardControllerFuchsia::AddObserver( - VirtualKeyboardControllerObserver* observer) { - NOTIMPLEMENTED(); -} + VirtualKeyboardControllerObserver* observer) {} void VirtualKeyboardControllerFuchsia::RemoveObserver( - VirtualKeyboardControllerObserver* observer) { - NOTIMPLEMENTED(); -} + VirtualKeyboardControllerObserver* observer) {} bool VirtualKeyboardControllerFuchsia::IsKeyboardVisible() { return keyboard_visible_; } +void VirtualKeyboardControllerFuchsia::WatchVisibility() { + if (!controller_service_) + return; + + controller_service_->WatchVisibility(fit::bind_member( + this, &VirtualKeyboardControllerFuchsia::OnVisibilityChange)); +} + +void VirtualKeyboardControllerFuchsia::OnVisibilityChange(bool is_visible) { + keyboard_visible_ = is_visible; + WatchVisibility(); +} + } // 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 f4118cd1d01..1adc5692e23 100644 --- a/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h +++ b/chromium/ui/base/ime/fuchsia/virtual_keyboard_controller_fuchsia.h @@ -5,10 +5,13 @@ #ifndef UI_BASE_IME_FUCHSIA_VIRTUAL_KEYBOARD_CONTROLLER_FUCHSIA_H_ #define UI_BASE_IME_FUCHSIA_VIRTUAL_KEYBOARD_CONTROLLER_FUCHSIA_H_ +#include #include +#include #include "base/component_export.h" #include "base/macros.h" +#include "ui/base/ime/input_method_base.h" #include "ui/base/ime/virtual_keyboard_controller.h" namespace ui { @@ -17,12 +20,15 @@ namespace ui { class COMPONENT_EXPORT(UI_BASE_IME) VirtualKeyboardControllerFuchsia : public VirtualKeyboardController { public: - // |ime_service| must outlive |this|. - explicit VirtualKeyboardControllerFuchsia( - fuchsia::ui::input::ImeService* ime_service); - + // |input_method| must outlive |this|. + VirtualKeyboardControllerFuchsia(fuchsia::ui::views::ViewRef view_ref, + ui::InputMethodBase* input_method); ~VirtualKeyboardControllerFuchsia() override; + VirtualKeyboardControllerFuchsia(VirtualKeyboardControllerFuchsia&) = delete; + VirtualKeyboardControllerFuchsia operator=( + VirtualKeyboardControllerFuchsia&) = delete; + // VirtualKeyboardController implementation. bool DisplayVirtualKeyboard() override; void DismissVirtualKeyboard() override; @@ -31,11 +37,15 @@ class COMPONENT_EXPORT(UI_BASE_IME) VirtualKeyboardControllerFuchsia bool IsKeyboardVisible() override; private: - fuchsia::ui::input::ImeService* const ime_service_; - fuchsia::ui::input::ImeVisibilityServicePtr ime_visibility_; - bool keyboard_visible_ = false; + // Initiates a "hanging get" request for virtual keyboard visibility. + void WatchVisibility(); - DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardControllerFuchsia); + // Handles the visibility change response from the service. + void OnVisibilityChange(bool is_visible); + + ui::InputMethodBase* const input_method_; + fuchsia::input::virtualkeyboard::ControllerPtr controller_service_; + bool keyboard_visible_ = false; }; } // namespace ui diff --git a/chromium/ui/base/ime/infolist_entry.cc b/chromium/ui/base/ime/infolist_entry.cc index 7423f73abb7..d050dce9c8c 100644 --- a/chromium/ui/base/ime/infolist_entry.cc +++ b/chromium/ui/base/ime/infolist_entry.cc @@ -6,8 +6,8 @@ namespace ui { -InfolistEntry::InfolistEntry(const base::string16& title, - const base::string16& body) +InfolistEntry::InfolistEntry(const std::u16string& title, + const std::u16string& body) : title(title), body(body), highlighted(false) {} bool InfolistEntry::operator==(const InfolistEntry& other) const { diff --git a/chromium/ui/base/ime/infolist_entry.h b/chromium/ui/base/ime/infolist_entry.h index 54d632005a6..36a8ba46d86 100644 --- a/chromium/ui/base/ime/infolist_entry.h +++ b/chromium/ui/base/ime/infolist_entry.h @@ -5,18 +5,19 @@ #ifndef UI_BASE_IME_INFOLIST_ENTRY_H_ #define UI_BASE_IME_INFOLIST_ENTRY_H_ +#include + #include "base/component_export.h" -#include "base/strings/string16.h" namespace ui { // The data model of infolist window. struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) InfolistEntry { - base::string16 title; - base::string16 body; + std::u16string title; + std::u16string body; bool highlighted; - InfolistEntry(const base::string16& title, const base::string16& body); + InfolistEntry(const std::u16string& title, const std::u16string& body); bool operator==(const InfolistEntry& entry) const; bool operator!=(const InfolistEntry& entry) const; }; diff --git a/chromium/ui/base/ime/input_method.h b/chromium/ui/base/ime/input_method.h index 0b91ccb01bb..a93dc25d794 100644 --- a/chromium/ui/base/ime/input_method.h +++ b/chromium/ui/base/ime/input_method.h @@ -77,6 +77,17 @@ class InputMethod { // used only for IME functionalities specific to Windows. virtual bool OnUntranslatedIMEMessage(const MSG event, NativeEventResult* result) = 0; + + // Called by the focused client whenever its input locale is changed. + // This method is currently used only on Windows. + // This method does not take a parameter of TextInputClient for historical + // reasons. + // TODO(ime): Consider to take a parameter of TextInputClient. + virtual void OnInputLocaleChanged() = 0; + + // Returns whether the system input locale is in CJK languages. + // This is only used in Windows platforms. + virtual bool IsInputLocaleCJK() const = 0; #endif // Sets the text input client which receives text input events such as @@ -117,17 +128,6 @@ class InputMethod { // focused client. virtual void CancelComposition(const TextInputClient* client) = 0; - // Called by the focused client whenever its input locale is changed. - // This method is currently used only on Windows. - // This method does not take a parameter of TextInputClient for historical - // reasons. - // TODO(ime): Consider to take a parameter of TextInputClient. - virtual void OnInputLocaleChanged() = 0; - - // Returns whether the system input locale is in CJK languages. - // This is only used in Windows platforms. - virtual bool IsInputLocaleCJK() const = 0; - // TODO(yoichio): Following 3 methods(GetTextInputType, GetTextInputMode and // CanComposeInline) calls client's same method and returns its value. It is // not InputMethod itself's infomation. So rename these to diff --git a/chromium/ui/base/ime/input_method_base.cc b/chromium/ui/base/ime/input_method_base.cc index 40245cc4261..73bfbfb06c6 100644 --- a/chromium/ui/base/ime/input_method_base.cc +++ b/chromium/ui/base/ime/input_method_base.cc @@ -47,6 +47,12 @@ bool InputMethodBase::OnUntranslatedIMEMessage( InputMethod::NativeEventResult* result) { return false; } + +void InputMethodBase::OnInputLocaleChanged() {} + +bool InputMethodBase::IsInputLocaleCJK() const { + return false; +} #endif void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) { @@ -75,13 +81,6 @@ void InputMethodBase::OnTextInputTypeChanged(const TextInputClient* client) { NotifyTextInputStateChanged(client); } -void InputMethodBase::OnInputLocaleChanged() { -} - -bool InputMethodBase::IsInputLocaleCJK() const { - return false; -} - TextInputType InputMethodBase::GetTextInputType() const { TextInputClient* client = GetTextInputClient(); return client ? client->GetTextInputType() : TEXT_INPUT_TYPE_NONE; diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h index 3c0d1a4c98f..b2886fd8dc4 100644 --- a/chromium/ui/base/ime/input_method_base.h +++ b/chromium/ui/base/ime/input_method_base.h @@ -45,6 +45,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase #if defined(OS_WIN) bool OnUntranslatedIMEMessage(const MSG event, NativeEventResult* result) override; + void OnInputLocaleChanged() override; + bool IsInputLocaleCJK() const override; #endif void SetFocusedTextInputClient(TextInputClient* client) override; @@ -55,9 +57,6 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase // If a derived class overrides this method, it should call parent's // implementation. void OnTextInputTypeChanged(const TextInputClient* client) override; - void OnInputLocaleChanged() override; - bool IsInputLocaleCJK() const override; - TextInputType GetTextInputType() const override; TextInputMode GetTextInputMode() const override; int GetTextInputFlags() const override; diff --git a/chromium/ui/base/ime/input_method_base_unittest.cc b/chromium/ui/base/ime/input_method_base_unittest.cc index 6c252435676..e5b4c290895 100644 --- a/chromium/ui/base/ime/input_method_base_unittest.cc +++ b/chromium/ui/base/ime/input_method_base_unittest.cc @@ -128,8 +128,6 @@ class MockInputMethodBase : public InputMethodBase { } void OnCaretBoundsChanged(const TextInputClient* client) override {} void CancelComposition(const TextInputClient* client) override {} - void OnInputLocaleChanged() override {} - bool IsInputLocaleCJK() const override { return false; } bool IsCandidatePopupOpen() const override { return false; } // InputMethodBase: diff --git a/chromium/ui/base/ime/linux/composition_text_util_pango.cc b/chromium/ui/base/ime/linux/composition_text_util_pango.cc index db18d1949f5..e985cc7b227 100644 --- a/chromium/ui/base/ime/linux/composition_text_util_pango.cc +++ b/chromium/ui/base/ime/linux/composition_text_util_pango.cc @@ -7,9 +7,10 @@ #include #include +#include + #include "base/i18n/char_iterator.h" #include "base/numerics/ranges.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/ime/composition_text.h" diff --git a/chromium/ui/base/ime/linux/fake_input_method_context.cc b/chromium/ui/base/ime/linux/fake_input_method_context.cc index c6c0479897d..36897c43744 100644 --- a/chromium/ui/base/ime/linux/fake_input_method_context.cc +++ b/chromium/ui/base/ime/linux/fake_input_method_context.cc @@ -28,8 +28,7 @@ void FakeInputMethodContext::SetCursorLocation(const gfx::Rect& rect) { } void FakeInputMethodContext::SetSurroundingText( - const base::string16& text, - const gfx::Range& selection_range) { -} + const std::u16string& text, + const gfx::Range& selection_range) {} } // namespace ui diff --git a/chromium/ui/base/ime/linux/fake_input_method_context.h b/chromium/ui/base/ime/linux/fake_input_method_context.h index 2b6953f1e87..4b9518a3275 100644 --- a/chromium/ui/base/ime/linux/fake_input_method_context.h +++ b/chromium/ui/base/ime/linux/fake_input_method_context.h @@ -23,7 +23,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) FakeInputMethodContext void Focus() override; void Blur() override; void SetCursorLocation(const gfx::Rect& rect) override; - void SetSurroundingText(const base::string16& text, + void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; private: diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.cc b/chromium/ui/base/ime/linux/input_method_auralinux.cc index f4725590f58..9388feaff2e 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux.cc +++ b/chromium/ui/base/ime/linux/input_method_auralinux.cc @@ -14,7 +14,17 @@ namespace { -const int kIgnoreCommitsDurationInMilliseconds = 100; +constexpr base::TimeDelta kIgnoreCommitsDuration = + base::TimeDelta::FromMilliseconds(100); + +bool IsEventFromVK(const ui::KeyEvent& event) { + if (event.HasNativeEvent()) + return false; + + const auto* properties = event.properties(); + return properties && + properties->find(ui::kPropertyFromVK) != properties->end(); +} } // namespace @@ -37,8 +47,7 @@ InputMethodAuraLinux::InputMethodAuraLinux( this, true); } -InputMethodAuraLinux::~InputMethodAuraLinux() { -} +InputMethodAuraLinux::~InputMethodAuraLinux() = default; LinuxInputMethodContext* InputMethodAuraLinux::GetContextForTesting( bool is_simple) { @@ -50,14 +59,13 @@ LinuxInputMethodContext* InputMethodAuraLinux::GetContextForTesting( ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent( ui::KeyEvent* event) { DCHECK(event->type() == ET_KEY_PRESSED || event->type() == ET_KEY_RELEASED); + ime_filtered_key_event_.reset(); // If no text input client, do nothing. if (!GetTextInputClient()) return DispatchKeyEventPostIME(event); - auto* properties = event->properties(); - if (!event->HasNativeEvent() && properties && - properties->find(ui::kPropertyFromVK) != properties->end()) { + if (IsEventFromVK(*event)) { // Faked key events that are sent from input.ime.sendKeyEvents. ui::EventDispatchDetails details = DispatchKeyEventPostIME(event); if (details.dispatcher_destroyed || details.target_destroyed || @@ -71,113 +79,76 @@ ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent( return details; } - suppress_non_key_input_until_ = base::TimeTicks::UnixEpoch(); - composition_changed_ = false; - result_text_.clear(); - + // Forward key event to IME. bool filtered = false; { + suppress_non_key_input_until_ = base::TimeTicks::UnixEpoch(); + composition_changed_ = false; + result_text_.clear(); + LinuxInputMethodContext* context = + text_input_type_ != TEXT_INPUT_TYPE_NONE && + text_input_type_ != TEXT_INPUT_TYPE_PASSWORD + ? context_.get() + : context_simple_.get(); base::AutoReset flipper(&is_sync_mode_, true); - if (text_input_type_ != TEXT_INPUT_TYPE_NONE && - text_input_type_ != TEXT_INPUT_TYPE_PASSWORD) { - filtered = context_->DispatchKeyEvent(*event); - } else { - filtered = context_simple_->DispatchKeyEvent(*event); - } + filtered = context->DispatchKeyEvent(*event); } - return ProcessKeyEventDone(event, filtered, false); -} - -ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone( - ui::KeyEvent* event, - bool filtered, - bool is_handled) { - DCHECK(event); - if (is_handled) + // There are four cases here. They are a pair of two conditions: + // - Whether KeyEvent is consumed by IME, which is represented by filtered. + // - Whether IME updates the commit/preedit string synchronously + // (i.e. which is already completed here), or asynchronously (i.e. which + // will be done afterwords, so not yet done). + // + // Note that there's a case that KeyEvent is reported as NOT consumed by IME, + // but IME still updates the commit/preedit. Please see below comment + // for more details. + // + // Conceptually, after IME's update, there're three things to be done. + // - Continue to dispatch the KeyEvent. + // - Update TextInputClient by using committed text. + // - Update TextInputClient by using preedit text. + // The following code does those three, except in the case that KeyEvent is + // 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()) { + ime_filtered_key_event_ = std::move(*event); return ui::EventDispatchDetails(); + } - // If the IME extension has not handled the key event, passes the keyevent - // back to the previous processing flow. Preconditions for this situation: - // 1) |filtered| == false - // 2) |filtered| == true && NeedInsertChar() + // First, if KeyEvent is consumed by IME, continue to dispatch it, + // before updating commit/preedit string so that, e.g., JavaScript keydown + // event is delivered to the page before keypress. ui::EventDispatchDetails details; if (event->type() == ui::ET_KEY_PRESSED && filtered) { - if (NeedInsertChar()) - details = DispatchKeyEventPostIME(event); - else if (HasInputMethodResult()) - details = SendFakeProcessKeyEvent(event); - if (details.dispatcher_destroyed) - return details; - // If the KEYDOWN is stopped propagation (e.g. triggered an accelerator), - // don't InsertChar/InsertText to the input field. - if (event->stopped_propagation() || details.target_destroyed) { - ResetContext(); + details = DispatchImeFilteredKeyPressEvent(event); + if (details.target_destroyed || details.dispatcher_destroyed || + event->stopped_propagation()) { return details; } - - // Don't send VKEY_PROCESSKEY event if there is no result text or - // composition. This is to workaround the weird behavior of IBus with US - // keyboard, which mutes the keydown and later fake a new keydown with IME - // result in sync mode. In that case, user would expect only - // keydown/keypress/keyup event without an initial 229 keydown event. } - bool should_stop_propagation = false; - // Note: |client| could be NULL because DispatchKeyEventPostIME could have - // changed the text input client. - TextInputClient* client = GetTextInputClient(); // Processes the result text before composition for sync mode. - if (client && !result_text_.empty()) { - if (filtered && NeedInsertChar()) { - for (const auto ch : result_text_) { - ui::KeyEvent ch_event(*event); - ch_event.set_character(ch); - client->InsertChar(ch_event); - // If the client changes we assume that the original target has been - // destroyed. - if (client != GetTextInputClient()) { - details.target_destroyed = true; - event->StopPropagation(); - return details; - } - } - } else { - // If |filtered| is false, that means the IME wants to commit some text - // but still release the key to the application. For example, Korean IME - // handles ENTER key to confirm its composition but still release it for - // the default behavior (e.g. trigger search, etc.) - // In such case, don't do InsertChar because a key should only trigger the - // keydown event once. - client->InsertText( - result_text_, - ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); - // If the client changes we assume that the original target has been - // destroyed. - if (client != GetTextInputClient()) { - details.target_destroyed = true; - event->StopPropagation(); - return details; - } - } - should_stop_propagation = true; - } - - if (client && composition_changed_ && !IsTextInputTypeNone()) { - // If composition changed, does SetComposition if composition is not empty. - // And ClearComposition if composition is empty. - if (!composition_.text.empty()) - client->SetCompositionText(composition_); - else if (result_text_.empty()) - client->ClearCompositionText(); - should_stop_propagation = true; + const auto commit_result = MaybeCommitResult(filtered, *event); + if (commit_result == CommitResult::kTargetDestroyed) { + details.target_destroyed = true; + event->StopPropagation(); + return details; } - - // Makes sure the cached composition is cleared after committing any text or - // cleared composition. - if (client && !client->HasCompositionText()) - composition_ = CompositionText(); - + // Stop the propagation if there's some committed characters. + // Note that this have to be done after the key event dispatching, + // specifically if key event is not reported as filtered. + bool should_stop_propagation = commit_result == CommitResult::kSuccess; + + // Then update the composition, if necessary. + // Should stop propagation of the event when composition is updated, + // because the event is considered to be used for the composition. + should_stop_propagation |= + MaybeUpdateComposition(commit_result == CommitResult::kSuccess); + + // If the IME has not handled the key event, passes the keyevent back to the + // previous processing flow. if (!filtered) { details = DispatchKeyEventPostIME(event); if (details.dispatcher_destroyed) { @@ -196,7 +167,7 @@ ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone( // TextInputClient::InsertChar(). // Note: don't use |client| and use GetTextInputClient() here because // DispatchKeyEventPostIME may cause the current text input client change. - base::char16 ch = event->GetCharacter(); + char16_t ch = event->GetCharacter(); if (ch && GetTextInputClient()) GetTextInputClient()->InsertChar(*event); should_stop_propagation = true; @@ -209,6 +180,101 @@ ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone( return details; } +ui::EventDispatchDetails InputMethodAuraLinux::DispatchImeFilteredKeyPressEvent( + ui::KeyEvent* event) { + // In general, 229 (VKEY_PROCESSKEY) should be used. However, in some IME + // framework, such as iBus/fcitx + GTK, the behavior is not simple as follows, + // in order to deal with synchronous API on asynchronous IME backend: + // - First, IM module reports the KeyEvent is filtered synchronously. + // - Then, it forwards the event to the IME engine asynchronously. + // - When IM module receives the result, and it turns out the event is not + // consumed, then IM module generates the same key event (with a special + // flag), and sent it to the application (Chrome in our case). + // - Then, the application forwards the event to IM module again, and in this + // time IM module synchronously commit the character. + // (Note: new iBus GTK IMModule changed the behavior, so the second event + // dispatch to the application won't happen). + // InputMethodAuraLinux detects this case by the following condition: + // - If result text is only one character, and + // - there's no composing text, and no updated. + // If the condition meets, that means IME did not consume the key event + // conceptually, so continue to dispatch KeyEvent without overwriting by 229. + ui::EventDispatchDetails details = NeedInsertChar(result_text_) + ? DispatchKeyEventPostIME(event) + : SendFakeProcessKeyEvent(event); + if (details.dispatcher_destroyed) + return details; + // If the KEYDOWN is stopped propagation (e.g. triggered an accelerator), + // don't InsertChar/InsertText to the input field. + if (event->stopped_propagation() || details.target_destroyed) + ResetContext(); + + return details; +} + +InputMethodAuraLinux::CommitResult InputMethodAuraLinux::MaybeCommitResult( + bool filtered, + const KeyEvent& event) { + // Take the ownership of |result_text_|. + std::u16string result_text = std::move(result_text_); + result_text_.clear(); + + // Note: |client| could be NULL because DispatchKeyEventPostIME could have + // changed the text input client. + TextInputClient* client = GetTextInputClient(); + if (!client || result_text.empty()) + return CommitResult::kNoCommitString; + + if (filtered && NeedInsertChar(result_text)) { + for (const auto ch : result_text) { + ui::KeyEvent ch_event(event); + ch_event.set_character(ch); + client->InsertChar(ch_event); + // If the client changes we assume that the original target has been + // destroyed. + if (client != GetTextInputClient()) + return CommitResult::kTargetDestroyed; + } + } else { + // If |filtered| is false, that means the IME wants to commit some text + // but still release the key to the application. For example, Korean IME + // handles ENTER key to confirm its composition but still release it for + // the default behavior (e.g. trigger search, etc.) + // In such case, don't do InsertChar because a key should only trigger the + // keydown event once. + client->InsertText( + result_text, + ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); + // If the client changes we assume that the original target has been + // destroyed. + if (client != GetTextInputClient()) + return CommitResult::kTargetDestroyed; + } + + return CommitResult::kSuccess; +} + +bool InputMethodAuraLinux::MaybeUpdateComposition(bool text_committed) { + TextInputClient* client = GetTextInputClient(); + bool update_composition = + client && composition_changed_ && !IsTextInputTypeNone(); + if (update_composition) { + // If composition changed, does SetComposition if composition is not empty. + // And ClearComposition if composition is empty. + if (!composition_.text.empty()) + client->SetCompositionText(composition_); + else if (!text_committed) + client->ClearCompositionText(); + } + + // Makes sure the cached composition is cleared after committing any text or + // cleared composition. + if (client && !client->HasCompositionText()) + composition_ = CompositionText(); + + return update_composition; +} + void InputMethodAuraLinux::UpdateContextFocusState() { bool old_text_input_type = text_input_type_; text_input_type_ = GetTextInputType(); @@ -245,7 +311,7 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) { context_->SetCursorLocation(GetTextInputClient()->GetCaretBounds()); gfx::Range text_range, selection_range; - base::string16 text; + std::u16string text; if (client->GetTextRange(&text_range) && client->GetTextFromRange(text_range, &text) && client->GetEditableSelectionRange(&selection_range)) { @@ -270,8 +336,7 @@ void InputMethodAuraLinux::ResetContext() { // If the IME has an open composition, ignore non-synchronous attempts to // commit text for a brief duration of time. suppress_non_key_input_until_ = - base::TimeTicks::Now() + - base::TimeDelta::FromMilliseconds(kIgnoreCommitsDurationInMilliseconds); + base::TimeTicks::Now() + kIgnoreCommitsDuration; } context_->Reset(); @@ -295,25 +360,30 @@ bool InputMethodAuraLinux::IsCandidatePopupOpen() const { // Overriden from ui::LinuxInputMethodContextDelegate -void InputMethodAuraLinux::OnCommit(const base::string16& text) { +void InputMethodAuraLinux::OnCommit(const std::u16string& text) { if (IgnoringNonKeyInput() || !GetTextInputClient()) return; - if (is_sync_mode_) { - // Append the text to the buffer, because commit signal might be fired - // multiple times when processing a key event. + // Discard the result iff in async-mode and the TextInputType is None + // for backward compatibility. + if (is_sync_mode_ || !IsTextInputTypeNone()) result_text_.append(text); - } else if (!IsTextInputTypeNone()) { - // If we are not handling key event, do not bother sending text result if - // the focused text input client does not support text input. - ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0); - ui::EventDispatchDetails details = SendFakeProcessKeyEvent(&event); - if (details.dispatcher_destroyed) + + // Sync mode means this is called on a stack of DispatchKeyEvent(), so its + // following code should handle the key dispatch and actual committing. + // If we are not handling key event, do not bother sending text result if + // the focused text input client does not support text input. + if (!is_sync_mode_ && !IsTextInputTypeNone()) { + ui::KeyEvent event = + ime_filtered_key_event_.has_value() + ? *ime_filtered_key_event_ + : ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0); + ui::EventDispatchDetails details = DispatchImeFilteredKeyPressEvent(&event); + if (details.target_destroyed || details.dispatcher_destroyed || + event.stopped_propagation()) { return; - if (!event.stopped_propagation() && !details.target_destroyed) - GetTextInputClient()->InsertText( - text, - ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText); + } + MaybeCommitResult(/*filtered=*/true, event); composition_ = CompositionText(); } } @@ -328,45 +398,13 @@ void InputMethodAuraLinux::OnDeleteSurroundingText(int32_t index, void InputMethodAuraLinux::OnPreeditChanged( const CompositionText& composition_text) { - if (IgnoringNonKeyInput() || IsTextInputTypeNone()) - return; - - if (is_sync_mode_) { - if (!composition_.text.empty() || !composition_text.text.empty()) - composition_changed_ = true; - } else { - ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0); - ui::EventDispatchDetails details = SendFakeProcessKeyEvent(&event); - if (details.dispatcher_destroyed) - return; - if (!event.stopped_propagation() && !details.target_destroyed) - GetTextInputClient()->SetCompositionText(composition_text); - } - - composition_ = composition_text; + OnPreeditUpdate(composition_text, !is_sync_mode_); } void InputMethodAuraLinux::OnPreeditEnd() { - if (IgnoringNonKeyInput() || IsTextInputTypeNone()) - return; - - if (is_sync_mode_) { - if (!composition_.text.empty()) { - composition_ = CompositionText(); - composition_changed_ = true; - } - } else { - TextInputClient* client = GetTextInputClient(); - if (client && client->HasCompositionText()) { - ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0); - ui::EventDispatchDetails details = SendFakeProcessKeyEvent(&event); - if (details.dispatcher_destroyed) - return; - if (!event.stopped_propagation() && !details.target_destroyed) - client->ClearCompositionText(); - } - composition_ = CompositionText(); - } + TextInputClient* client = GetTextInputClient(); + OnPreeditUpdate(CompositionText(), + !is_sync_mode_ && client && client->HasCompositionText()); } // Overridden from InputMethodBase. @@ -392,14 +430,38 @@ void InputMethodAuraLinux::OnDidChangeFocusedClient( // private +void InputMethodAuraLinux::OnPreeditUpdate( + const ui::CompositionText& composition_text, + bool force_update_client) { + if (IgnoringNonKeyInput() || IsTextInputTypeNone()) + return; + + composition_changed_ |= composition_ != composition_text; + composition_ = composition_text; + + if (!force_update_client) + return; + ui::KeyEvent event = + ime_filtered_key_event_.has_value() + ? *ime_filtered_key_event_ + : ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, 0); + ui::EventDispatchDetails details = DispatchImeFilteredKeyPressEvent(&event); + if (details.target_destroyed || details.dispatcher_destroyed || + event.stopped_propagation()) { + return; + } + MaybeUpdateComposition(/*text_committed=*/false); +} + bool InputMethodAuraLinux::HasInputMethodResult() { return !result_text_.empty() || composition_changed_; } -bool InputMethodAuraLinux::NeedInsertChar() const { +bool InputMethodAuraLinux::NeedInsertChar( + const std::u16string& result_text) const { return IsTextInputTypeNone() || (!composition_changed_ && composition_.text.empty() && - result_text_.length() == 1); + result_text.length() == 1); } ui::EventDispatchDetails InputMethodAuraLinux::SendFakeProcessKeyEvent( diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.h b/chromium/ui/base/ime/linux/input_method_auralinux.h index 52c1cc614c9..5118102b902 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 #include "base/component_export.h" -#include "base/macros.h" +#include "base/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" @@ -23,6 +23,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux public LinuxInputMethodContextDelegate { public: explicit InputMethodAuraLinux(internal::InputMethodDelegate* delegate); + InputMethodAuraLinux(const InputMethodAuraLinux&) = delete; + InputMethodAuraLinux& operator=(const InputMethodAuraLinux&) = delete; ~InputMethodAuraLinux() override; LinuxInputMethodContext* GetContextForTesting(bool is_simple); @@ -35,7 +37,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux bool IsCandidatePopupOpen() const override; // Overriden from ui::LinuxInputMethodContextDelegate - void OnCommit(const base::string16& text) override; + void OnCommit(const std::u16string& text) override; void OnDeleteSurroundingText(int32_t index, uint32_t length) override; void OnPreeditChanged(const CompositionText& composition_text) override; void OnPreeditEnd() override; @@ -49,26 +51,41 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux TextInputClient* focused) override; private: + // Continues to dispatch the ET_KEY_PRESSED event to the client. + // This needs to be called "before" committing the result string or + // the composition string. + ui::EventDispatchDetails DispatchImeFilteredKeyPressEvent( + ui::KeyEvent* event); + enum class CommitResult { + kSuccess, // Successfully committed at least one character. + kNoCommitString, // No available string to commit. + kTargetDestroyed, // Target was destroyed during the commit. + }; + CommitResult MaybeCommitResult(bool filtered, const KeyEvent& event); + bool MaybeUpdateComposition(bool text_committed); + + // Shared implementation of OnPreeditChanged and OnPreeditEnd. + // |force_update_client| is designed to dispatch key event/update + // the client's composition string, specifically for async-mode case. + void OnPreeditUpdate(const ui::CompositionText& composition_text, + bool force_update_client); void ConfirmCompositionText(); bool HasInputMethodResult(); - bool NeedInsertChar() const; + bool NeedInsertChar(const std::u16string& result_text) const; ui::EventDispatchDetails SendFakeProcessKeyEvent(ui::KeyEvent* event) const WARN_UNUSED_RESULT; void UpdateContextFocusState(); void ResetContext(); bool IgnoringNonKeyInput() const; - // Processes the key event after the event is processed by the system IME or - // the extension. - ui::EventDispatchDetails ProcessKeyEventDone(ui::KeyEvent* event, - bool filtered, - bool is_handled) - WARN_UNUSED_RESULT; - std::unique_ptr context_; std::unique_ptr context_simple_; - base::string16 result_text_; + // The last key event that IME is probably in process in + // async-mode. + base::Optional ime_filtered_key_event_; + + std::u16string result_text_; ui::CompositionText composition_; @@ -89,8 +106,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux // Used for making callbacks. base::WeakPtrFactory weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(InputMethodAuraLinux); }; } // namespace ui 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 3f2de2f7597..f62edbede72 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc +++ b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc @@ -21,10 +21,10 @@ namespace ui { namespace { -const base::char16 kActionCommit = L'C'; -const base::char16 kActionCompositionStart = L'S'; -const base::char16 kActionCompositionUpdate = L'U'; -const base::char16 kActionCompositionEnd = L'E'; +const char16_t kActionCommit = L'C'; +const char16_t kActionCompositionStart = L'S'; +const char16_t kActionCompositionUpdate = L'U'; +const char16_t kActionCompositionEnd = L'E'; class TestResult { public: @@ -32,7 +32,7 @@ class TestResult { return base::Singleton::get(); } - void RecordAction(const base::string16& action) { + void RecordAction(const std::u16string& action) { recorded_actions_.push_back(action); } @@ -51,8 +51,8 @@ class TestResult { } private: - std::vector recorded_actions_; - std::vector expected_actions_; + std::vector recorded_actions_; + std::vector expected_actions_; }; class LinuxInputMethodContextForTesting : public LinuxInputMethodContext { @@ -75,13 +75,9 @@ class LinuxInputMethodContextForTesting : public LinuxInputMethodContext { actions_.push_back(base::ASCIIToUTF16("U:" + text)); } - void AddCompositionStartAction() { - actions_.push_back(base::ASCIIToUTF16("S")); - } + void AddCompositionStartAction() { actions_.push_back(u"S"); } - void AddCompositionEndAction() { - actions_.push_back(base::ASCIIToUTF16("E")); - } + void AddCompositionEndAction() { actions_.push_back(u"E"); } protected: bool DispatchKeyEvent(const ui::KeyEvent& key_event) override { @@ -91,11 +87,11 @@ class LinuxInputMethodContextForTesting : public LinuxInputMethodContext { } for (const auto& action : actions_) { - std::vector parts = base::SplitString( - action, base::string16(1, ':'), base::TRIM_WHITESPACE, - base::SPLIT_WANT_ALL); - base::char16 id = parts[0][0]; - base::string16 param; + std::vector parts = + base::SplitString(action, std::u16string(1, ':'), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + char16_t id = parts[0][0]; + std::u16string param; if (parts.size() > 1) param = parts[1]; if (id == kActionCommit) { @@ -125,10 +121,9 @@ class LinuxInputMethodContextForTesting : public LinuxInputMethodContext { cursor_position_ = rect; } - void SetSurroundingText(const base::string16& text, + void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override { - TestResult::GetInstance()->RecordAction( - base::ASCIIToUTF16("surroundingtext:") + text); + TestResult::GetInstance()->RecordAction(u"surroundingtext:" + text); std::stringstream rs; rs << "selectionrangestart:" << selection_range.start(); @@ -140,7 +135,7 @@ class LinuxInputMethodContextForTesting : public LinuxInputMethodContext { private: LinuxInputMethodContextDelegate* delegate_; - std::vector actions_; + std::vector actions_; bool is_sync_mode_; bool eat_key_; bool focused_; @@ -199,18 +194,17 @@ class TextInputClientForTesting : public DummyTextInputClient { explicit TextInputClientForTesting(TextInputType text_input_type) : DummyTextInputClient(text_input_type) {} - base::string16 composition_text; + std::u16string composition_text; gfx::Range text_range; gfx::Range selection_range; - base::string16 surrounding_text; + std::u16string surrounding_text; protected: void SetCompositionText(const CompositionText& composition) override { composition_text = composition.text; - TestResult::GetInstance()->RecordAction( - base::ASCIIToUTF16("compositionstart")); - TestResult::GetInstance()->RecordAction( - base::ASCIIToUTF16("compositionupdate:") + composition.text); + TestResult::GetInstance()->RecordAction(u"compositionstart"); + TestResult::GetInstance()->RecordAction(u"compositionupdate:" + + composition.text); } bool HasCompositionText() const override { return !composition_text.empty(); } @@ -221,10 +215,8 @@ class TextInputClientForTesting : public DummyTextInputClient { if (keep_selection) { NOTIMPLEMENTED_LOG_ONCE(); } - TestResult::GetInstance()->RecordAction( - base::ASCIIToUTF16("compositionend")); - TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16("textinput:") + - composition_text); + TestResult::GetInstance()->RecordAction(u"compositionend"); + TestResult::GetInstance()->RecordAction(u"textinput:" + composition_text); const uint32_t composition_text_length = static_cast(composition_text.length()); composition_text.clear(); @@ -232,27 +224,24 @@ class TextInputClientForTesting : public DummyTextInputClient { } void ClearCompositionText() override { - TestResult::GetInstance()->RecordAction( - base::ASCIIToUTF16("compositionend")); + TestResult::GetInstance()->RecordAction(u"compositionend"); composition_text.clear(); } void InsertText( - const base::string16& text, + const std::u16string& text, TextInputClient::InsertTextCursorBehavior cursor_behavior) override { if (HasCompositionText()) { - TestResult::GetInstance()->RecordAction( - base::ASCIIToUTF16("compositionend")); + TestResult::GetInstance()->RecordAction(u"compositionend"); } - TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16("textinput:") + - text); + TestResult::GetInstance()->RecordAction(u"textinput:" + text); composition_text.clear(); } void InsertChar(const ui::KeyEvent& event) override { std::stringstream ss; ss << event.GetCharacter(); - TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16("keypress:") + + TestResult::GetInstance()->RecordAction(u"keypress:" + base::ASCIIToUTF16(ss.str())); } @@ -265,7 +254,7 @@ class TextInputClientForTesting : public DummyTextInputClient { return true; } bool GetTextFromRange(const gfx::Range& range, - base::string16* text) const override { + std::u16string* text) const override { if (surrounding_text.empty()) return false; *text = surrounding_text.substr(range.GetMin(), range.length()); @@ -375,10 +364,18 @@ TEST_F(InputMethodAuraLinuxTest, BasicAsyncModeTest) { key_new.set_character(L'a'); KeyEvent key = key_new; input_method_auralinux_->DispatchKeyEvent(&key); - input_method_auralinux_->OnCommit(base::ASCIIToUTF16("a")); + input_method_auralinux_->OnCommit(u"a"); + + test_result_->ExpectAction("keydown:65"); + test_result_->ExpectAction("keypress:97"); + test_result_->Verify(); + + key = key_new; + input_method_auralinux_->DispatchKeyEvent(&key); + input_method_auralinux_->OnCommit(u"foo"); test_result_->ExpectAction("keydown:229"); - test_result_->ExpectAction("textinput:a"); + test_result_->ExpectAction("textinput:foo"); test_result_->Verify(); input_method_auralinux_->DetachTextInputClient(client.get()); @@ -447,7 +444,7 @@ TEST_F(InputMethodAuraLinuxTest, IBusPinyinTest) { // IBus issues a standalone set_composition action. input_method_auralinux_->OnPreeditStart(); CompositionText comp; - comp.text = base::ASCIIToUTF16("a"); + comp.text = u"a"; input_method_auralinux_->OnPreeditChanged(comp); test_result_->ExpectAction("keydown:229"); @@ -460,7 +457,7 @@ TEST_F(InputMethodAuraLinuxTest, IBusPinyinTest) { input_method_auralinux_->DispatchKeyEvent(&key_up); input_method_auralinux_->OnPreeditEnd(); - input_method_auralinux_->OnCommit(base::ASCIIToUTF16("A")); + input_method_auralinux_->OnCommit(u"A"); test_result_->ExpectAction("keydown:229"); test_result_->ExpectAction("compositionend"); @@ -700,7 +697,7 @@ TEST_F(InputMethodAuraLinuxTest, MixedAsyncAndSyncTest) { KeyEvent key = key_new; input_method_auralinux_->DispatchKeyEvent(&key); CompositionText comp; - comp.text = base::ASCIIToUTF16("a"); + comp.text = u"a"; input_method_auralinux_->OnPreeditChanged(comp); test_result_->ExpectAction("keydown:229"); @@ -746,7 +743,7 @@ TEST_F(InputMethodAuraLinuxTest, MixedSyncAndAsyncTest) { key = key_new; input_method_auralinux_->DispatchKeyEvent(&key); - input_method_auralinux_->OnCommit(base::ASCIIToUTF16("b")); + input_method_auralinux_->OnCommit(u"b"); test_result_->ExpectAction("keydown:229"); test_result_->ExpectAction("compositionend"); @@ -810,7 +807,7 @@ TEST_F(InputMethodAuraLinuxTest, SurroundingText_NoSelectionTest) { input_method_auralinux_->SetFocusedTextInputClient(client.get()); input_method_auralinux_->OnTextInputTypeChanged(client.get()); - client->surrounding_text = base::ASCIIToUTF16("abcdef"); + client->surrounding_text = u"abcdef"; client->text_range = gfx::Range(0, 6); client->selection_range = gfx::Range(3, 3); @@ -828,7 +825,7 @@ TEST_F(InputMethodAuraLinuxTest, SurroundingText_SelectionTest) { input_method_auralinux_->SetFocusedTextInputClient(client.get()); input_method_auralinux_->OnTextInputTypeChanged(client.get()); - client->surrounding_text = base::ASCIIToUTF16("abcdef"); + client->surrounding_text = u"abcdef"; client->text_range = gfx::Range(0, 6); client->selection_range = gfx::Range(2, 5); @@ -846,7 +843,7 @@ TEST_F(InputMethodAuraLinuxTest, SurroundingText_PartialText) { input_method_auralinux_->SetFocusedTextInputClient(client.get()); input_method_auralinux_->OnTextInputTypeChanged(client.get()); - client->surrounding_text = base::ASCIIToUTF16("abcdefghij"); + client->surrounding_text = u"abcdefghij"; client->text_range = gfx::Range(5, 10); client->selection_range = gfx::Range(7, 9); diff --git a/chromium/ui/base/ime/linux/linux_input_method_context.h b/chromium/ui/base/ime/linux/linux_input_method_context.h index 5e4f410d12f..4fe9ac63b4d 100644 --- a/chromium/ui/base/ime/linux/linux_input_method_context.h +++ b/chromium/ui/base/ime/linux/linux_input_method_context.h @@ -5,8 +5,9 @@ #ifndef UI_BASE_IME_LINUX_LINUX_INPUT_METHOD_CONTEXT_H_ #define UI_BASE_IME_LINUX_LINUX_INPUT_METHOD_CONTEXT_H_ +#include + #include "base/component_export.h" -#include "base/strings/string16.h" #include "ui/base/ime/text_input_type.h" namespace gfx { @@ -35,7 +36,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) LinuxInputMethodContext { virtual void SetCursorLocation(const gfx::Rect& rect) = 0; // Tells the system IME the surrounding text around the cursor location. - virtual void SetSurroundingText(const base::string16& text, + virtual void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) = 0; // Resets the context. A client needs to call OnTextInputTypeChanged() again @@ -55,7 +56,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) LinuxInputMethodContextDelegate { virtual ~LinuxInputMethodContextDelegate() {} // Commits the |text| to the text input client. - virtual void OnCommit(const base::string16& text) = 0; + virtual void OnCommit(const std::u16string& text) = 0; // Deletes the surrounding text at |index| for given |length|. virtual void OnDeleteSurroundingText(int32_t index, uint32_t length) = 0; diff --git a/chromium/ui/base/ime/mock_input_method.cc b/chromium/ui/base/ime/mock_input_method.cc index 35fa91b0dec..fa2dec5bb7a 100644 --- a/chromium/ui/base/ime/mock_input_method.cc +++ b/chromium/ui/base/ime/mock_input_method.cc @@ -70,6 +70,12 @@ bool MockInputMethod::OnUntranslatedIMEMessage(const MSG event, *result = NativeEventResult(); return false; } + +void MockInputMethod::OnInputLocaleChanged() {} + +bool MockInputMethod::IsInputLocaleCJK() const { + return false; +} #endif void MockInputMethod::OnTextInputTypeChanged(const TextInputClient* client) { @@ -85,13 +91,6 @@ void MockInputMethod::OnCaretBoundsChanged(const TextInputClient* client) { void MockInputMethod::CancelComposition(const TextInputClient* client) { } -void MockInputMethod::OnInputLocaleChanged() { -} - -bool MockInputMethod::IsInputLocaleCJK() const { - return false; -} - TextInputType MockInputMethod::GetTextInputType() const { return TEXT_INPUT_TYPE_NONE; } diff --git a/chromium/ui/base/ime/mock_input_method.h b/chromium/ui/base/ime/mock_input_method.h index 4074c5a30a7..6fdd6306826 100644 --- a/chromium/ui/base/ime/mock_input_method.h +++ b/chromium/ui/base/ime/mock_input_method.h @@ -38,6 +38,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethod : public InputMethod { #if defined(OS_WIN) bool OnUntranslatedIMEMessage(const MSG event, NativeEventResult* result) override; + void OnInputLocaleChanged() override; + bool IsInputLocaleCJK() const override; #endif void SetFocusedTextInputClient(TextInputClient* client) override; @@ -47,8 +49,6 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethod : public InputMethod { void OnTextInputTypeChanged(const TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; - void OnInputLocaleChanged() override; - bool IsInputLocaleCJK() const override; TextInputType GetTextInputType() const override; TextInputMode GetTextInputMode() const override; int GetTextInputFlags() const override; diff --git a/chromium/ui/base/ime/text_input_client.h b/chromium/ui/base/ime/text_input_client.h index 51e67bb0523..e9a5e3724b9 100644 --- a/chromium/ui/base/ime/text_input_client.h +++ b/chromium/ui/base/ime/text_input_client.h @@ -9,13 +9,13 @@ #include #if defined(OS_WIN) +#include #include #endif #include "base/component_export.h" #include "base/i18n/rtl.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -36,6 +36,8 @@ class KeyEvent; enum class TextEditCommand; // An interface implemented by a View that needs text input support. +// All strings related to IME operations should be UTF-16 encoded and all +// indices/ranges relative to those strings should be UTF-16 code units. class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { public: // The reason the control was focused, used by the virtual keyboard to detect @@ -95,7 +97,7 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { // Inserts a given text at the insertion point. Current composition text or // selection will be removed. This method should never be called when the // current text input type is TEXT_INPUT_TYPE_NONE. - virtual void InsertText(const base::string16& text, + virtual void InsertText(const std::u16string& text, InsertTextCursorBehavior cursor_behavior) = 0; // Inserts a single char at the insertion point. Unlike above InsertText() @@ -185,7 +187,7 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { // Returns false if the operation is not supported or the specified range // is out of the text range returned by GetTextRange(). virtual bool GetTextFromRange(const gfx::Range& range, - base::string16* text) const = 0; + std::u16string* text) const = 0; // Miscellaneous ------------------------------------------------------------ @@ -277,7 +279,7 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { // composition has been committed or not. virtual void SetActiveCompositionForAccessibility( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool is_composition_committed) = 0; #endif diff --git a/chromium/ui/base/ime/utf_offset.cc b/chromium/ui/base/ime/utf_offset.cc index f6d4bd13d50..7991f6bf21f 100644 --- a/chromium/ui/base/ime/utf_offset.cc +++ b/chromium/ui/base/ime/utf_offset.cc @@ -6,7 +6,6 @@ #include -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" @@ -19,7 +18,7 @@ base::Optional Utf16OffsetFromUtf8Offset(base::StringPiece text, // TODO(hidehiko): Update not to depend on UTF8ToUTF16 to avoid // unnecessary memory allocation. - base::string16 converted; + std::u16string converted; if (!base::UTF8ToUTF16(text.data(), utf8_offset, &converted)) return base::nullopt; return converted.length(); diff --git a/chromium/ui/base/ime/utf_offset_unittest.cc b/chromium/ui/base/ime/utf_offset_unittest.cc index 1deb7d626bc..cf0a6aeb03f 100644 --- a/chromium/ui/base/ime/utf_offset_unittest.cc +++ b/chromium/ui/base/ime/utf_offset_unittest.cc @@ -4,9 +4,10 @@ #include "ui/base/ime/utf_offset.h" +#include + #include "base/logging.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "testing/gtest/include/gtest/gtest.h" @@ -128,12 +129,9 @@ TEST(UtfOffsetTest, Utf8OffsetFromUtf16Offset) { }; for (const auto& test_case : kTestCases) { - // TODO(crbug.com/911896): Get rid of reinterpret_cast on switching - // to char16_t. - base::string16 text(reinterpret_cast(test_case.str)); EXPECT_EQ(test_case.expect, - Utf8OffsetFromUtf16Offset(text, test_case.offset)) - << " at " << text << "[" << test_case.offset << "]"; + Utf8OffsetFromUtf16Offset(test_case.str, test_case.offset)) + << " at " << test_case.str << "[" << test_case.offset << "]"; } } diff --git a/chromium/ui/base/ime/win/imm32_manager.cc b/chromium/ui/base/ime/win/imm32_manager.cc index 26f17604d02..f0588dd4dbc 100644 --- a/chromium/ui/base/ime/win/imm32_manager.cc +++ b/chromium/ui/base/ime/win/imm32_manager.cc @@ -7,19 +7,14 @@ #include #include +#include #include "base/macros.h" -#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/ime/composition_text.h" -// Following code requires wchar_t to be same as char16. It should always be -// true on Windows. -static_assert(sizeof(wchar_t) == sizeof(base::char16), - "wchar_t should be the same size as char16"); - /////////////////////////////////////////////////////////////////////////////// // IMM32Manager @@ -337,9 +332,9 @@ void IMM32Manager::GetCompositionInfo(HIMC imm_context, } bool IMM32Manager::GetString(HIMC imm_context, - WPARAM lparam, - int type, - base::string16* result) { + WPARAM lparam, + int type, + std::u16string* result) { if (!(lparam & type)) return false; LONG string_size = ::ImmGetCompositionString(imm_context, type, NULL, 0); @@ -347,13 +342,15 @@ bool IMM32Manager::GetString(HIMC imm_context, return false; DCHECK_EQ(0u, string_size % sizeof(wchar_t)); ::ImmGetCompositionString(imm_context, type, - base::WriteInto(result, (string_size / sizeof(wchar_t)) + 1), - string_size); + base::as_writable_wcstr(base::WriteInto( + result, (string_size / sizeof(wchar_t)) + 1)), + string_size); return true; } -bool IMM32Manager::GetResult( - HWND window_handle, LPARAM lparam, base::string16* result) { +bool IMM32Manager::GetResult(HWND window_handle, + LPARAM lparam, + std::u16string* result) { bool ret = false; HIMC imm_context = ::ImmGetContext(window_handle); if (imm_context) { diff --git a/chromium/ui/base/ime/win/imm32_manager.h b/chromium/ui/base/ime/win/imm32_manager.h index 7edb11e515e..d876eca1ec3 100644 --- a/chromium/ui/base/ime/win/imm32_manager.h +++ b/chromium/ui/base/ime/win/imm32_manager.h @@ -13,7 +13,6 @@ #include "base/component_export.h" #include "base/i18n/rtl.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/base/ime/text_input_mode.h" #include "ui/gfx/geometry/rect.h" @@ -149,7 +148,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) IMM32Manager { // the same parameter of a WM_IME_COMPOSITION message handler. // This parameter is used for checking if the ongoing composition has // its result string, - // * result [out] (base::string16) + // * result [out] (std::u16string) // Represents the object contains the composition result. // Return values // * true @@ -159,7 +158,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) IMM32Manager { // Remarks // This function is designed for being called from WM_IME_COMPOSITION // message handlers. - bool GetResult(HWND window_handle, LPARAM lparam, base::string16* result); + bool GetResult(HWND window_handle, LPARAM lparam, std::u16string* result); // Retrieves the current composition status of the ongoing composition. // Parameters @@ -262,7 +261,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) IMM32Manager { bool GetString(HIMC imm_context, WPARAM lparam, int type, - base::string16* result); + std::u16string* result); private: // Represents whether or not there is an ongoing composition in a browser diff --git a/chromium/ui/base/ime/win/input_method_win_base.cc b/chromium/ui/base/ime/win/input_method_win_base.cc index f07ce6fef45..bc80f95a689 100644 --- a/chromium/ui/base/ime/win/input_method_win_base.cc +++ b/chromium/ui/base/ime/win/input_method_win_base.cc @@ -198,18 +198,14 @@ ui::EventDispatchDetails InputMethodWinBase::DispatchKeyEvent( // the WM_KEY*. // Chrome never handles dead chars so it is safe to remove/ignore // WM_*DEADCHAR messages. - MSG msg; - while (::PeekMessage(&msg, native_key_event.hwnd, WM_CHAR, WM_DEADCHAR, - PM_REMOVE)) { - if (msg.message == WM_CHAR) - char_msgs.push_back(msg); + if (!HandlePeekMessage(native_key_event.hwnd, WM_CHAR, WM_DEADCHAR, + &char_msgs)) { + return DispatcherDestroyedDetails(); } - while (::PeekMessage(&msg, native_key_event.hwnd, WM_SYSCHAR, WM_SYSDEADCHAR, - PM_REMOVE)) { - if (msg.message == WM_SYSCHAR) - char_msgs.push_back(msg); + if (!HandlePeekMessage(native_key_event.hwnd, WM_SYSCHAR, WM_SYSDEADCHAR, + &char_msgs)) { + return DispatcherDestroyedDetails(); } - // Handles ctrl-shift key to change text direction and layout alignment. if (IsRTLKeyboardLayoutInstalled() && !IsTextInputTypeNone()) { ui::KeyboardCode code = event->key_code(); @@ -233,11 +229,31 @@ ui::EventDispatchDetails InputMethodWinBase::DispatchKeyEvent( // If only 1 WM_CHAR per the key event, set it as the character of it. if (char_msgs.size() == 1 && !std::iswcntrl(static_cast(char_msgs[0].wParam))) - event->set_character(static_cast(char_msgs[0].wParam)); + event->set_character(char16_t{char_msgs[0].wParam}); return ProcessUnhandledKeyEvent(event, &char_msgs); } +bool InputMethodWinBase::HandlePeekMessage(HWND hwnd, + UINT msg_filter_min, + UINT msg_filter_max, + std::vector* char_msgs) { + auto ref = weak_ptr_factory_.GetWeakPtr(); + while (true) { + MSG msg_found; + const bool result = !!::PeekMessage(&msg_found, hwnd, msg_filter_min, + msg_filter_max, PM_REMOVE); + // PeekMessage may result in WM_NCDESTROY which will cause deletion of + // |this|. We should use WeakPtr to check whether |this| is destroyed. + if (!ref) + return false; + if (result && msg_found.message == msg_filter_min) + char_msgs->push_back(msg_found); + if (!result) + return true; + } +} + bool InputMethodWinBase::IsWindowFocused(const TextInputClient* client) const { if (!client) return false; @@ -261,8 +277,8 @@ LRESULT InputMethodWinBase::OnChar(HWND window_handle, // We need to send character events to the focused text input client event if // its text input type is ui::TEXT_INPUT_TYPE_NONE. if (GetTextInputClient()) { - const base::char16 kCarriageReturn = L'\r'; - const base::char16 ch = static_cast(wparam); + const char16_t kCarriageReturn = L'\r'; + const char16_t ch{wparam}; // A mask to determine the previous key state from |lparam|. The value is 1 // if the key is down before the message is sent, or it is 0 if the key is // up. @@ -347,7 +363,7 @@ LRESULT InputMethodWinBase::OnDocumentFeed(RECONVERTSTRING* reconv) { if (reconv->dwSize < need_size) return 0; - base::string16 text; + std::u16string text; if (!GetTextInputClient()->GetTextFromRange(text_range, &text)) return 0; DCHECK_EQ(text_range.length(), text.length()); @@ -403,7 +419,7 @@ LRESULT InputMethodWinBase::OnReconvertString(RECONVERTSTRING* reconv) { // TODO(penghuang): Return some extra context to help improve IME's // reconversion accuracy. - base::string16 text; + std::u16string text; if (!GetTextInputClient()->GetTextFromRange(selection_range, &text)) return 0; DCHECK_EQ(selection_range.length(), text.length()); diff --git a/chromium/ui/base/ime/win/input_method_win_base.h b/chromium/ui/base/ime/win/input_method_win_base.h index c788c6b5f35..60306824f62 100644 --- a/chromium/ui/base/ime/win/input_method_win_base.h +++ b/chromium/ui/base/ime/win/input_method_win_base.h @@ -79,6 +79,13 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinBase // Used for making callbacks. base::WeakPtrFactory weak_ptr_factory_{this}; + private: + // Return false if |this| is destroyed during |PeekMessage| call. + bool HandlePeekMessage(HWND hwnd, + UINT msg_filter_min, + UINT msg_filter_max, + std::vector* char_msgs); + DISALLOW_COPY_AND_ASSIGN(InputMethodWinBase); }; 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 d75398fb64b..6a4a9a6dc77 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,10 +4,11 @@ #include +#include + #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "base/test/task_environment.h" #include "base/win/windows_version.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chromium/ui/base/ime/win/tsf_text_store.cc b/chromium/ui/base/ime/win/tsf_text_store.cc index 5289629ade9..b0968cc0d12 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.cc +++ b/chromium/ui/base/ime/win/tsf_text_store.cc @@ -286,7 +286,7 @@ HRESULT TSFTextStore::GetText(LONG acp_start, acp_end = std::min(acp_end, acp_start + static_cast(text_buffer_size)); *text_buffer_copied = acp_end - acp_start; - const base::string16& result = + const std::u16string& result = string_buffer_document_.substr(acp_start, *text_buffer_copied); for (size_t i = 0; i < result.size(); ++i) { text_buffer[i] = result[i]; @@ -495,7 +495,7 @@ HRESULT TSFTextStore::InsertTextAtSelection(DWORD flags, DCHECK_LE(start_pos, end_pos); string_buffer_document_ = string_buffer_document_.substr(0, start_pos) + - base::string16(text_buffer, text_buffer + text_buffer_size) + + std::u16string(text_buffer, text_buffer + text_buffer_size) + string_buffer_document_.substr(end_pos); // reconstruct string that needs to be inserted. @@ -698,7 +698,7 @@ HRESULT TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) { is_tic_write_in_progress_ = false; } - const base::string16& composition_string = string_buffer_document_.substr( + const std::u16string& composition_string = string_buffer_document_.substr( composition_range_.GetMin(), composition_range_.length()); // Only need to set composition if the current composition string @@ -1141,7 +1141,7 @@ void TSFTextStore::CalculateTextandSelectionDiffAndNotifyIfNeeded() { TRACE_EVENT0("ime", "TSFTextStore::CalculateTextandSelectionDiffAndNotifyIfNeeded"); gfx::Range latest_buffer_range_from_client; - base::string16 latest_buffer_from_client; + std::u16string latest_buffer_from_client; gfx::Range latest_selection_from_client; if (text_input_client_->GetTextRange(&latest_buffer_range_from_client) && @@ -1421,7 +1421,7 @@ void TSFTextStore::CommitTextAndEndCompositionIfAny(size_t old_size, } // Construct string to be committed. - const base::string16& new_committed_string = string_buffer_document_.substr( + const std::u16string& new_committed_string = string_buffer_document_.substr( new_committed_string_offset, new_committed_string_size); // TODO(crbug.com/978678): Unify the behavior of // |TextInputClient::InsertText(text)| for the empty text. @@ -1456,7 +1456,7 @@ void TSFTextStore::CommitTextAndEndCompositionIfAny(size_t old_size, void TSFTextStore::StartCompositionOnNewText( size_t start_offset, - const base::string16& composition_string) { + const std::u16string& composition_string) { CompositionText composition_text; composition_text.text = composition_string; composition_text.ime_text_spans = text_spans_; @@ -1488,7 +1488,7 @@ void TSFTextStore::StartCompositionOnNewText( /*is_composition_committed*/ false); } else { // User wants to commit the current composition - const base::string16& committed_string = string_buffer_document_.substr( + const std::u16string& committed_string = string_buffer_document_.substr( composition_range_.GetMin(), composition_range_.length()); text_input_client_->SetActiveCompositionForAccessibility( composition_range_, committed_string, diff --git a/chromium/ui/base/ime/win/tsf_text_store.h b/chromium/ui/base/ime/win/tsf_text_store.h index f41d80116ba..e0f0219e31f 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.h +++ b/chromium/ui/base/ime/win/tsf_text_store.h @@ -8,11 +8,11 @@ #include #include #include +#include #include "base/compiler_specific.h" #include "base/component_export.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/events/event_utils.h" @@ -276,7 +276,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore // Start new composition with new text. void StartCompositionOnNewText(size_t start_offset, - const base::string16& composition_string); + const std::u16string& composition_string); // Commit and insert text into TextInputClient. End any ongoing composition. void CommitTextAndEndCompositionIfAny(size_t old_size, size_t new_size) const; @@ -335,8 +335,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore // |has_composition_range_| = true; // |composition_range_start_| = 3; // |composition_range_end_| = 6; - base::string16 string_buffer_document_; - base::string16 string_pending_insertion_; + std::u16string string_buffer_document_; + std::u16string string_pending_insertion_; size_t composition_start_ = 0; bool has_composition_range_ = false; gfx::Range composition_range_; @@ -354,7 +354,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore // change to blink if IME only change the selection range but not the // composition text. |previous_text_spans_| saves the IME spans in previous // edit session during same composition. - base::string16 previous_composition_string_; + std::u16string previous_composition_string_; size_t previous_composition_start_ = 0; gfx::Range previous_composition_selection_range_ = gfx::Range::InvalidRange(); ImeTextSpans previous_text_spans_; @@ -376,7 +376,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore // |buffer_from_client_| contains all string returned from // TextInputClient::GetTextFromRange(); - base::string16 buffer_from_client_; + std::u16string buffer_from_client_; // |selection_from_client_| indicates the selection range returned from // TextInputClient::GetEditableSelectionRange(); 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 8b13dc1df3c..ef9b1fa3510 100644 --- a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc +++ b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc @@ -39,7 +39,7 @@ class MockTextInputClient : public TextInputClient { MOCK_METHOD0(ClearCompositionText, void()); MOCK_METHOD2( InsertText, - void(const base::string16&, + void(const std::u16string&, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior)); MOCK_METHOD1(InsertChar, void(const ui::KeyEvent&)); MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType()); @@ -58,7 +58,7 @@ class MockTextInputClient : public TextInputClient { MOCK_METHOD1(SetEditableSelectionRange, bool(const gfx::Range&)); MOCK_METHOD1(DeleteRange, bool(const gfx::Range&)); MOCK_CONST_METHOD2(GetTextFromRange, - bool(const gfx::Range&, base::string16*)); + bool(const gfx::Range&, std::u16string*)); MOCK_METHOD0(OnInputMethodChanged, void()); MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment, bool(base::i18n::TextDirection)); @@ -70,7 +70,7 @@ class MockTextInputClient : public TextInputClient { MOCK_METHOD2(SetCompositionFromExistingText, bool(const gfx::Range&, const std::vector&)); MOCK_METHOD3(SetActiveCompositionForAccessibility, - void(const gfx::Range&, const base::string16&, bool)); + void(const gfx::Range&, const std::u16string&, bool)); MOCK_METHOD2(GetActiveTextInputControlLayoutBounds, void(base::Optional* control_bounds, base::Optional* selection_bounds)); @@ -158,7 +158,7 @@ class TSFTextStoreTest : public testing::Test { } // Accessors to the internal state of TSFTextStore. - base::string16* string_buffer() { + std::u16string* string_buffer() { return &text_store_->string_buffer_document_; } size_t* composition_start() { return &text_store_->composition_start_; } @@ -184,7 +184,7 @@ class TSFTextStoreTestCallback { range->set_end(text_range_.end()); return true; } - bool GetTextFromRange(const gfx::Range& range, base::string16* text) { + bool GetTextFromRange(const gfx::Range& range, std::u16string* text) { *text = text_buffer_.substr(range.GetMin(), range.length()); return true; } @@ -204,10 +204,10 @@ class TSFTextStoreTestCallback { // Accessors to the internal state of TSFTextStore. bool* edit_flag() { return &text_store_->edit_flag_; } bool* new_text_inserted() { return &text_store_->new_text_inserted_; } - base::string16* string_buffer() { + std::u16string* string_buffer() { return &text_store_->string_buffer_document_; } - base::string16* string_pending_insertion() { + std::u16string* string_pending_insertion() { return &text_store_->string_pending_insertion_; } size_t* composition_start() { return &text_store_->composition_start_; } @@ -216,7 +216,7 @@ class TSFTextStoreTestCallback { gfx::Range* composition_range() { return &text_store_->composition_range_; } bool* has_composition_range() { return &text_store_->has_composition_range_; } - void SetInternalState(const base::string16& new_string_buffer, + void SetInternalState(const std::u16string& new_string_buffer, LONG new_composition_start, LONG new_selection_start, LONG new_selection_end) { @@ -401,7 +401,7 @@ class TSFTextStoreTestCallback { composition_range_.set_end(end); } - void SetTextBuffer(const base::char16* buffer) { + void SetTextBuffer(const char16_t* buffer) { text_buffer_.clear(); text_buffer_.assign(buffer); } @@ -410,7 +410,7 @@ class TSFTextStoreTestCallback { gfx::Range text_range_; gfx::Range selection_range_; gfx::Range composition_range_; - base::string16 text_buffer_; + std::u16string text_buffer_; scoped_refptr text_store_; private: @@ -432,7 +432,7 @@ TEST_F(TSFTextStoreTest, GetStatusTest) { TEST_F(TSFTextStoreTest, QueryInsertTest) { LONG result_start = 0; LONG result_end = 0; - *string_buffer() = base::string16(); + *string_buffer() = std::u16string(); *composition_start() = 0; EXPECT_EQ(E_INVALIDARG, text_store_->QueryInsert(0, 0, 0, nullptr, &result_end)); @@ -442,7 +442,7 @@ TEST_F(TSFTextStoreTest, QueryInsertTest) { text_store_->QueryInsert(0, 0, 0, &result_start, &result_end)); EXPECT_EQ(0, result_start); EXPECT_EQ(0, result_end); - *string_buffer() = STRING16_LITERAL("1234"); + *string_buffer() = u"1234"; *composition_start() = 1; EXPECT_EQ(S_OK, text_store_->QueryInsert(0, 1, 0, &result_start, &result_end)); @@ -657,7 +657,7 @@ class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback { EXPECT_TRUE(HasReadWriteLock()); *edit_flag() = true; - SetInternalState(STRING16_LITERAL("012345"), 6, 6, 6); + SetInternalState(u"012345", 6, 6, 6); text_spans()->clear(); state_ = 2; @@ -665,10 +665,10 @@ class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback { } void InsertText( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { EXPECT_EQ(2, state_); - EXPECT_EQ(STRING16_LITERAL("012345"), text); + EXPECT_EQ(u"012345", text); state_ = 3; } @@ -678,8 +678,8 @@ class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback { return true; } - bool GetTextFromRange(const gfx::Range& range, base::string16* text) const { - base::string16 string_buffer = STRING16_LITERAL("012345"); + bool GetTextFromRange(const gfx::Range& range, std::u16string* text) const { + std::u16string string_buffer = u"012345"; *text = string_buffer.substr(range.GetMin(), range.length()); return true; } @@ -755,12 +755,12 @@ class SelectionTestCallback : public TSFTextStoreTestCallback { : TSFTextStoreTestCallback(text_store) {} HRESULT ReadLockGranted(DWORD flags) { - SetInternalState(base::string16(), 0, 0, 0); + SetInternalState(std::u16string(), 0, 0, 0); GetSelectionTest(0, 0); SetSelectionTest(0, 0, TF_E_NOLOCK); - SetInternalState(STRING16_LITERAL("012345"), 0, 0, 3); + SetInternalState(u"012345", 0, 0, 3); GetSelectionTest(0, 3); SetSelectionTest(0, 0, TF_E_NOLOCK); @@ -769,7 +769,7 @@ class SelectionTestCallback : public TSFTextStoreTestCallback { } HRESULT ReadWriteLockGranted(DWORD flags) { - SetInternalState(base::string16(), 0, 0, 0); + SetInternalState(std::u16string(), 0, 0, 0); SetSelectionTest(0, 0, S_OK); GetSelectionTest(0, 0); @@ -777,7 +777,7 @@ class SelectionTestCallback : public TSFTextStoreTestCallback { SetSelectionTest(1, 0, TF_E_INVALIDPOS); SetSelectionTest(1, 1, TF_E_INVALIDPOS); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetSelectionTest(0, 0, S_OK); SetSelectionTest(0, 1, S_OK); @@ -854,7 +854,7 @@ class SetGetTextTestCallback : public TSFTextStoreTestCallback { GetTextTest(0, 0, L"", 0); GetTextErrorTest(0, 1, TF_E_INVALIDPOS); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); GetTextErrorTest(-1, -1, TF_E_INVALIDPOS); GetTextErrorTest(-1, 0, TF_E_INVALIDPOS); @@ -916,13 +916,13 @@ class SetGetTextTestCallback : public TSFTextStoreTestCallback { } HRESULT ReadWriteLockGranted(DWORD flags) { - SetInternalState(base::string16(), 0, 0, 0); + SetInternalState(std::u16string(), 0, 0, 0); SetTextTest(0, 0, L"", S_OK); - SetInternalState(base::string16(), 0, 0, 0); + SetInternalState(std::u16string(), 0, 0, 0); SetTextTest(0, 1, L"", TS_E_INVALIDPOS); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(0, 0, L"", S_OK); SetTextTest(0, 1, L"", S_OK); @@ -944,17 +944,17 @@ class SetGetTextTestCallback : public TSFTextStoreTestCallback { SetTextTest(3, 3, L"", TS_E_INVALIDPOS); GetTextTest(0, -1, L"4", 1); GetSelectionTest(1, 1); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(3, 6, L"", S_OK); GetTextTest(0, -1, L"0126", 4); GetSelectionTest(3, 3); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(3, 7, L"", S_OK); GetTextTest(0, -1, L"012", 3); GetSelectionTest(3, 3); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(3, 8, L"", TS_E_INVALIDPOS); @@ -965,12 +965,12 @@ class SetGetTextTestCallback : public TSFTextStoreTestCallback { SetTextTest(6, 6, L"", S_OK); GetTextTest(0, -1, L"0123456", 7); GetSelectionTest(6, 6); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(6, 7, L"", S_OK); GetTextTest(0, -1, L"012345", 6); GetSelectionTest(6, 6); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(6, 8, L"", TS_E_INVALIDPOS); @@ -982,36 +982,36 @@ class SetGetTextTestCallback : public TSFTextStoreTestCallback { SetTextTest(7, 7, L"", S_OK); GetTextTest(0, -1, L"0123456", 7); GetSelectionTest(7, 7); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(7, 8, L"", TS_E_INVALIDPOS); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(3, 3, L"abc", S_OK); GetTextTest(0, -1, L"012abc3456", 10); GetSelectionTest(3, 6); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(3, 6, L"abc", S_OK); GetTextTest(0, -1, L"012abc6", 7); GetSelectionTest(3, 6); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(3, 7, L"abc", S_OK); GetTextTest(0, -1, L"012abc", 6); GetSelectionTest(3, 6); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(6, 6, L"abc", S_OK); GetTextTest(0, -1, L"012345abc6", 10); GetSelectionTest(6, 9); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(6, 7, L"abc", S_OK); GetTextTest(0, -1, L"012345abc", 9); GetSelectionTest(6, 9); - SetInternalState(STRING16_LITERAL("0123456"), 3, 3, 3); + SetInternalState(u"0123456", 3, 3, 3); SetTextTest(7, 7, L"abc", S_OK); GetTextTest(0, -1, L"0123456abc", 10); GetSelectionTest(7, 10); @@ -1054,12 +1054,12 @@ class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback { HRESULT ReadLockGranted(DWORD flags) { const wchar_t kBuffer[] = L"0123456789"; - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 0, 0); + SetInternalState(u"abcedfg", 0, 0, 0); InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0); GetSelectionTest(0, 0); InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0); - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 2, 5); + SetInternalState(u"abcedfg", 0, 2, 5); InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 2, 5); GetSelectionTest(2, 5); InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 2, 5); @@ -1073,34 +1073,34 @@ class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback { } HRESULT ReadWriteLockGranted(DWORD flags) { - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 0, 0); + SetInternalState(u"abcedfg", 0, 0, 0); const wchar_t kBuffer[] = L"0123456789"; InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0); GetSelectionTest(0, 0); InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0); - SetInternalState(base::string16(), 0, 0, 0); + SetInternalState(std::u16string(), 0, 0, 0); InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10); GetSelectionTest(0, 10); GetTextTest(0, -1, L"0123456789", 10); - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 0, 0); + SetInternalState(u"abcedfg", 0, 0, 0); InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10); GetSelectionTest(0, 10); GetTextTest(0, -1, L"0123456789abcedfg", 17); - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 0, 3); + SetInternalState(u"abcedfg", 0, 0, 3); InsertTextAtSelectionTest(kBuffer, 0, 0, 0, 0, 3, 0); GetSelectionTest(0, 0); GetTextTest(0, -1, L"edfg", 4); - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 3, 7); + SetInternalState(u"abcedfg", 0, 3, 7); InsertTextAtSelectionTest(kBuffer, 10, 3, 13, 3, 7, 13); GetSelectionTest(3, 13); GetTextTest(0, -1, L"abc0123456789", 13); - SetInternalState(STRING16_LITERAL("abcedfg"), 0, 7, 7); + SetInternalState(u"abcedfg", 0, 7, 7); InsertTextAtSelectionTest(kBuffer, 10, 7, 17, 7, 7, 17); GetSelectionTest(7, 17); GetTextTest(0, -1, L"abcedfg0123456789", 17); @@ -1161,7 +1161,7 @@ class ScenarioTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("axyzc"), composition.text); + EXPECT_EQ(u"axyzc", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(5u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1196,13 +1196,13 @@ class ScenarioTestCallback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("axy"), text); + EXPECT_EQ(u"axy", text); } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("ZCPc"), composition.text); + EXPECT_EQ(u"ZCPc", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1224,9 +1224,9 @@ class ScenarioTestCallback : public TSFTextStoreTestCallback { } void InsertText3( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("ZCPc"), text); + EXPECT_EQ(u"ZCPc", text); has_composition_text_ = false; } @@ -1254,7 +1254,7 @@ class ScenarioTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText4(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("EFGH"), composition.text); + EXPECT_EQ(u"EFGH", composition.text); EXPECT_EQ(4u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1285,7 +1285,7 @@ class ScenarioTestCallback : public TSFTextStoreTestCallback { // still need to call into TextInputClient to set composition text // to update selection range even though composition text is unchanged. void SetCompositionText5(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("EFGH"), composition.text); + EXPECT_EQ(u"EFGH", composition.text); EXPECT_EQ(2u, composition.selection.start()); EXPECT_EQ(2u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1345,7 +1345,7 @@ class GetTextExtTestCallback : public TSFTextStoreTestCallback { layout_prepared_character_num_(0) {} HRESULT LockGranted(DWORD flags) { - SetInternalState(STRING16_LITERAL("0123456789012"), 0, 0, 0); + SetInternalState(u"0123456789012", 0, 0, 0); layout_prepared_character_num_ = 13; has_composition_text_ = true; @@ -1371,23 +1371,23 @@ class GetTextExtTestCallback : public TSFTextStoreTestCallback { has_composition_text_ = false; GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6); - SetInternalState(base::string16(), 0, 0, 0); + SetInternalState(std::u16string(), 0, 0, 0); GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6); // Last character is not available due to timing issue of async API. // In this case, we will get first character bounds instead of whole text // bounds. - SetInternalState(STRING16_LITERAL("abc"), 0, 0, 3); + SetInternalState(u"abc", 0, 0, 3); layout_prepared_character_num_ = 2; has_composition_text_ = true; GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20); // TODO(nona, kinaba): Remove following test case after PPAPI supporting // GetCompositionCharacterBounds. - SetInternalState(STRING16_LITERAL("a"), 0, 0, 1); + SetInternalState(u"a", 0, 0, 1); layout_prepared_character_num_ = 0; GetTextExtTest(view_cookie, 0, 1, 1, 2, 4, 6); - SetInternalState(STRING16_LITERAL("abc"), 0, 0, 3); + SetInternalState(u"abc", 0, 0, 3); GetTextExtNoLayoutTest(view_cookie, 2, 3); return S_OK; @@ -1538,7 +1538,7 @@ class KeyEventTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1582,14 +1582,14 @@ class KeyEventTestCallback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("B"), composition.text); + EXPECT_EQ(u"B", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1627,9 +1627,9 @@ class KeyEventTestCallback : public TSFTextStoreTestCallback { } void InsertText3( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("B"), text); + EXPECT_EQ(u"B", text); SetHasCompositionText(false); } @@ -1723,7 +1723,7 @@ class AccessibilityEventTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -1739,9 +1739,9 @@ class AccessibilityEventTestCallback : public TSFTextStoreTestCallback { void SetActiveCompositionForAccessibility1( const gfx::Range& range, - const base::string16& active_composition_text, + const std::u16string& active_composition_text, bool committed_composition) { - EXPECT_EQ(STRING16_LITERAL("a"), active_composition_text); + EXPECT_EQ(u"a", active_composition_text); EXPECT_EQ(0u, range.start()); EXPECT_EQ(1u, range.end()); } @@ -1798,7 +1798,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { GetTextTest(0, -1, L"", 0); SetTextRange(0, 1); - SetTextBuffer(STRING16_LITERAL("a")); + SetTextBuffer(u"a"); SetSelectionRange(1, 1); *composition_start() = 1; return S_OK; @@ -1844,17 +1844,17 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("bcde"), text); + EXPECT_EQ(u"bcde", text); SetTextRange(0, 5); SetSelectionRange(5, 5); - SetTextBuffer(STRING16_LITERAL("abcde")); + SetTextBuffer(u"abcde"); } HRESULT LockGranted3(DWORD flags) { SetTextRange(0, 5); - SetTextBuffer(STRING16_LITERAL("about")); + SetTextBuffer(u"about"); SetSelectionRange(0, 5); return S_OK; } @@ -1890,7 +1890,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted4(DWORD flags) { SetTextRange(0, 5); - SetTextBuffer(STRING16_LITERAL("abFGt")); + SetTextBuffer(u"abFGt"); SetSelectionRange(3, 4); return S_OK; } @@ -1926,7 +1926,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted5(DWORD flags) { SetTextRange(0, 3); - SetTextBuffer(STRING16_LITERAL("aHI")); + SetTextBuffer(u"aHI"); SetSelectionRange(3, 3); return S_OK; } @@ -1962,7 +1962,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted6(DWORD flags) { SetTextRange(0, 5); - SetTextBuffer(STRING16_LITERAL("JKLMN")); + SetTextBuffer(u"JKLMN"); SetSelectionRange(2, 5); return S_OK; } @@ -1998,7 +1998,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted7(DWORD flags) { SetTextRange(0, 0); - SetTextBuffer(STRING16_LITERAL("")); + SetTextBuffer(u""); SetSelectionRange(0, 0); return S_OK; } @@ -2034,7 +2034,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted8(DWORD flags) { SetTextRange(0, 3); - SetTextBuffer(STRING16_LITERAL("OPQ")); + SetTextBuffer(u"OPQ"); SetSelectionRange(0, 2); return S_OK; } @@ -2070,7 +2070,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted9(DWORD flags) { SetTextRange(0, 3); - SetTextBuffer(STRING16_LITERAL("OPR")); + SetTextBuffer(u"OPR"); SetSelectionRange(2, 3); return S_OK; } @@ -2106,7 +2106,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { HRESULT LockGranted10(DWORD flags) { SetTextRange(0, 3); - SetTextBuffer(STRING16_LITERAL("SPR")); + SetTextBuffer(u"SPR"); SetSelectionRange(0, 1); return S_OK; } @@ -2142,7 +2142,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { // 11. renderer proc changes buffer from "SPR" to "STPR". HRESULT LockGranted11(DWORD flags) { SetTextRange(0, 4); - SetTextBuffer(STRING16_LITERAL("STPR")); + SetTextBuffer(u"STPR"); SetSelectionRange(2, 2); return S_OK; } @@ -2179,7 +2179,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { // 12. renderer proc changes buffer from "STPR" to "PR". HRESULT LockGranted12(DWORD flags) { SetTextRange(0, 2); - SetTextBuffer(STRING16_LITERAL("PR")); + SetTextBuffer(u"PR"); SetSelectionRange(0, 0); return S_OK; } @@ -2216,7 +2216,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { // 13. renderer proc changes buffer from "PR" to "UPR". HRESULT LockGranted13(DWORD flags) { SetTextRange(0, 3); - SetTextBuffer(STRING16_LITERAL("UPR")); + SetTextBuffer(u"UPR"); SetSelectionRange(1, 1); return S_OK; } @@ -2253,7 +2253,7 @@ class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback { // 14. renderer proc changes buffer from "UPR" to "UPVWR". HRESULT LockGranted14(DWORD flags) { SetTextRange(0, 5); - SetTextBuffer(STRING16_LITERAL("UPVWR")); + SetTextBuffer(u"UPVWR"); SetSelectionRange(4, 4); return S_OK; } @@ -2501,7 +2501,7 @@ class RegressionTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -2552,14 +2552,14 @@ class RegressionTestCallback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -2586,9 +2586,9 @@ class RegressionTestCallback : public TSFTextStoreTestCallback { } void InsertText3( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); } @@ -2618,15 +2618,15 @@ class RegressionTestCallback : public TSFTextStoreTestCallback { // We expect this call since the composition was started and committed during // same edit session. void SetCompositionText4(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("c"), composition.text); + EXPECT_EQ(u"c", composition.text); ASSERT_EQ(1u, composition.ime_text_spans.size()); ASSERT_EQ(gfx::Range(1, 1), composition.selection); } void InsertText4( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("c"), text); + EXPECT_EQ(u"c", text); } HRESULT LockGranted5(DWORD flags) { @@ -2662,7 +2662,7 @@ class RegressionTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText5(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("d"), composition.text); + EXPECT_EQ(u"d", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -2692,9 +2692,9 @@ class RegressionTestCallback : public TSFTextStoreTestCallback { } void InsertText6( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("e"), text); + EXPECT_EQ(u"e", text); SetHasCompositionText(false); } @@ -2802,7 +2802,7 @@ class RegressionTest2Callback : public TSFTextStoreTestCallback { } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("DE"), composition.text); + EXPECT_EQ(u"DE", composition.text); EXPECT_EQ(2u, composition.selection.start()); EXPECT_EQ(2u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -2830,9 +2830,9 @@ class RegressionTest2Callback : public TSFTextStoreTestCallback { } void InsertText3( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("DE"), text); + EXPECT_EQ(u"DE", text); SetHasCompositionText(false); } @@ -2901,7 +2901,7 @@ class RegressionTest3Callback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -2932,7 +2932,7 @@ class RegressionTest3Callback : public TSFTextStoreTestCallback { } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(base::string16(), composition.text); + EXPECT_EQ(std::u16string(), composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(0u, composition.selection.end()); ASSERT_EQ(0u, composition.ime_text_spans.size()); @@ -3001,7 +3001,7 @@ class RegressionTest4Callback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3030,9 +3030,9 @@ class RegressionTest4Callback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); } @@ -3105,7 +3105,7 @@ class RegressionTest5Callback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("aa"), composition.text); + EXPECT_EQ(u"aa", composition.text); EXPECT_EQ(2u, composition.selection.start()); EXPECT_EQ(2u, composition.selection.end()); ASSERT_EQ(2u, composition.ime_text_spans.size()); @@ -3148,7 +3148,7 @@ class RegressionTest5Callback : public TSFTextStoreTestCallback { } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("aa"), composition.text); + EXPECT_EQ(u"aa", composition.text); EXPECT_EQ(2u, composition.selection.start()); EXPECT_EQ(2u, composition.selection.end()); ASSERT_EQ(2u, composition.ime_text_spans.size()); @@ -3174,9 +3174,9 @@ class RegressionTest5Callback : public TSFTextStoreTestCallback { } void InsertText3( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("aa"), text); + EXPECT_EQ(u"aa", text); SetHasCompositionText(false); } @@ -3249,7 +3249,7 @@ class RegressionTest6Callback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(1u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3273,9 +3273,9 @@ class RegressionTest6Callback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); } @@ -3339,7 +3339,7 @@ class UnderlineStyleTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3440,9 +3440,9 @@ class RegressionTest7Callback : public TSFTextStoreTestCallback { } void InsertText3( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); } @@ -3511,7 +3511,7 @@ class RegressionTest8Callback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("bbbb"), composition.text); + EXPECT_EQ(u"bbbb", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3605,7 +3605,7 @@ class RegressionTest9Callback : public TSFTextStoreTestCallback { } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("bbbb"), composition.text); + EXPECT_EQ(u"bbbb", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3637,7 +3637,7 @@ class RegressionTest9Callback : public TSFTextStoreTestCallback { } void SetCompositionText3(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("bbcc"), composition.text); + EXPECT_EQ(u"bbcc", composition.text); EXPECT_EQ(2u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3662,9 +3662,9 @@ class RegressionTest9Callback : public TSFTextStoreTestCallback { } void InsertText4( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("bbcc"), text); + EXPECT_EQ(u"bbcc", text); SetHasCompositionText(false); } @@ -3745,7 +3745,7 @@ class RegressionTest10Callback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("abcd"), composition.text); + EXPECT_EQ(u"abcd", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -3787,7 +3787,7 @@ class RegressionTest10Callback : public TSFTextStoreTestCallback { } void SetCompositionText2(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("abcd"), composition.text); + EXPECT_EQ(u"abcd", composition.text); EXPECT_EQ(2u, composition.selection.start()); EXPECT_EQ(2u, composition.selection.end()); ASSERT_EQ(2u, composition.ime_text_spans.size()); @@ -3895,7 +3895,7 @@ class RegressionTest11Callback : public TSFTextStoreTestCallback { } void SetCompositionText(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("abcd"), composition.text); + EXPECT_EQ(u"abcd", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(4u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -4027,7 +4027,7 @@ class MultipleSetTextCallback : public TSFTextStoreTestCallback { HRESULT LockGranted1(DWORD flags) { SetTextRange(0, 6); - SetTextBuffer(STRING16_LITERAL("123456")); + SetTextBuffer(u"123456"); SetTextTest(0, 0, L"123456", S_OK); SetSelectionRange(6, 6); *composition_start() = 1; @@ -4135,7 +4135,7 @@ class TextInputClientReentrancyTestCallback : public TSFTextStoreTestCallback { } void SetCompositionText1(const ui::CompositionText& composition) { - EXPECT_EQ(STRING16_LITERAL("a"), composition.text); + EXPECT_EQ(u"a", composition.text); EXPECT_EQ(0u, composition.selection.start()); EXPECT_EQ(1u, composition.selection.end()); ASSERT_EQ(1u, composition.ime_text_spans.size()); @@ -4143,7 +4143,7 @@ class TextInputClientReentrancyTestCallback : public TSFTextStoreTestCallback { EXPECT_EQ(1u, composition.ime_text_spans[0].end_offset); SetHasCompositionText(true); SetTextRange(0, 1); - SetTextBuffer(STRING16_LITERAL("a")); + SetTextBuffer(u"a"); SetSelectionRange(0, 1); } @@ -4161,12 +4161,12 @@ class TextInputClientReentrancyTestCallback : public TSFTextStoreTestCallback { } void InsertText2( - const base::string16& text, + const std::u16string& text, ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) { - EXPECT_EQ(STRING16_LITERAL("a"), text); + EXPECT_EQ(u"a", text); SetHasCompositionText(false); SetSelectionRange(1, 1); - SetTextBuffer(STRING16_LITERAL("b")); + SetTextBuffer(u"b"); HRESULT result = kInvalidResult; EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); EXPECT_EQ(S_OK, result); diff --git a/chromium/ui/base/l10n/formatter.cc b/chromium/ui/base/l10n/formatter.cc index 684ead8c0a0..4770ef0e642 100644 --- a/chromium/ui/base/l10n/formatter.cc +++ b/chromium/ui/base/l10n/formatter.cc @@ -280,7 +280,7 @@ std::unique_ptr Formatter::CreateFallbackFormat( std::unique_ptr Formatter::InitFormat( const Pluralities& pluralities) { if (!formatter_force_fallback) { - base::string16 pattern = l10n_util::GetStringUTF16(pluralities.id); + std::u16string pattern = l10n_util::GetStringUTF16(pluralities.id); UErrorCode error = U_ZERO_ERROR; std::unique_ptr format(new icu::MessageFormat( icu::UnicodeString(false, pattern.data(), pattern.length()), error)); @@ -306,32 +306,32 @@ FormatterContainer::~FormatterContainer() { } void FormatterContainer::Initialize() { - formatter_[TimeFormat::FORMAT_ELAPSED][TimeFormat::LENGTH_SHORT].reset( - new Formatter(IDS_ELAPSED_SHORT_SEC, IDS_ELAPSED_SHORT_MIN, - IDS_ELAPSED_HOUR, IDS_ELAPSED_DAY, IDS_ELAPSED_MONTH, - IDS_ELAPSED_YEAR)); - formatter_[TimeFormat::FORMAT_ELAPSED][TimeFormat::LENGTH_LONG].reset( - new Formatter(IDS_ELAPSED_LONG_SEC, IDS_ELAPSED_LONG_MIN, - IDS_ELAPSED_HOUR, IDS_ELAPSED_DAY, IDS_ELAPSED_MONTH, - IDS_ELAPSED_YEAR)); - formatter_[TimeFormat::FORMAT_REMAINING][TimeFormat::LENGTH_SHORT].reset( - new Formatter(IDS_REMAINING_SHORT_SEC, IDS_REMAINING_SHORT_MIN, - IDS_REMAINING_HOUR, IDS_REMAINING_DAY, IDS_REMAINING_MONTH, - IDS_REMAINING_YEAR)); - formatter_[TimeFormat::FORMAT_REMAINING][TimeFormat::LENGTH_LONG].reset( - new Formatter(IDS_REMAINING_LONG_SEC, IDS_REMAINING_LONG_MIN, - IDS_REMAINING_HOUR, IDS_REMAINING_DAY, IDS_REMAINING_MONTH, - IDS_REMAINING_YEAR)); - formatter_[TimeFormat::FORMAT_DURATION][TimeFormat::LENGTH_SHORT].reset( - new Formatter(IDS_DURATION_SHORT_SEC, IDS_DURATION_SHORT_MIN, - IDS_DURATION_HOUR, IDS_DURATION_DAY, IDS_DURATION_MONTH, - IDS_DURATION_YEAR)); - formatter_[TimeFormat::FORMAT_DURATION][TimeFormat::LENGTH_LONG].reset( - new Formatter(IDS_LONG_SEC, IDS_LONG_MIN, IDS_DURATION_HOUR, - IDS_DURATION_DAY, IDS_DURATION_MONTH, IDS_DURATION_YEAR, - IDS_LONG_MIN_1ST, IDS_LONG_SEC_2ND, IDS_DURATION_HOUR_1ST, - IDS_LONG_MIN_2ND, IDS_DURATION_DAY_1ST, - IDS_DURATION_HOUR_2ND)); + formatter_[TimeFormat::FORMAT_ELAPSED][TimeFormat::LENGTH_SHORT] = + std::make_unique(IDS_ELAPSED_SHORT_SEC, IDS_ELAPSED_SHORT_MIN, + IDS_ELAPSED_HOUR, IDS_ELAPSED_DAY, + IDS_ELAPSED_MONTH, IDS_ELAPSED_YEAR); + formatter_[TimeFormat::FORMAT_ELAPSED][TimeFormat::LENGTH_LONG] = + std::make_unique(IDS_ELAPSED_LONG_SEC, IDS_ELAPSED_LONG_MIN, + IDS_ELAPSED_HOUR, IDS_ELAPSED_DAY, + IDS_ELAPSED_MONTH, IDS_ELAPSED_YEAR); + formatter_[TimeFormat::FORMAT_REMAINING][TimeFormat::LENGTH_SHORT] = + std::make_unique( + IDS_REMAINING_SHORT_SEC, IDS_REMAINING_SHORT_MIN, IDS_REMAINING_HOUR, + IDS_REMAINING_DAY, IDS_REMAINING_MONTH, IDS_REMAINING_YEAR); + formatter_[TimeFormat::FORMAT_REMAINING][TimeFormat::LENGTH_LONG] = + std::make_unique( + IDS_REMAINING_LONG_SEC, IDS_REMAINING_LONG_MIN, IDS_REMAINING_HOUR, + IDS_REMAINING_DAY, IDS_REMAINING_MONTH, IDS_REMAINING_YEAR); + formatter_[TimeFormat::FORMAT_DURATION][TimeFormat::LENGTH_SHORT] = + std::make_unique( + IDS_DURATION_SHORT_SEC, IDS_DURATION_SHORT_MIN, IDS_DURATION_HOUR, + IDS_DURATION_DAY, IDS_DURATION_MONTH, IDS_DURATION_YEAR); + formatter_[TimeFormat::FORMAT_DURATION][TimeFormat::LENGTH_LONG] = + std::make_unique( + IDS_LONG_SEC, IDS_LONG_MIN, IDS_DURATION_HOUR, IDS_DURATION_DAY, + IDS_DURATION_MONTH, IDS_DURATION_YEAR, IDS_LONG_MIN_1ST, + IDS_LONG_SEC_2ND, IDS_DURATION_HOUR_1ST, IDS_LONG_MIN_2ND, + IDS_DURATION_DAY_1ST, IDS_DURATION_HOUR_2ND); } void FormatterContainer::Shutdown() { diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc index 8004a13658e..c69597f5aa5 100644 --- a/chromium/ui/base/l10n/l10n_util.cc +++ b/chromium/ui/base/l10n/l10n_util.cc @@ -19,7 +19,6 @@ #include "base/i18n/number_formatting.h" #include "base/i18n/rtl.h" #include "base/i18n/string_compare.h" -#include "base/i18n/uchar.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/no_destructor.h" @@ -320,12 +319,11 @@ bool HasStringsForLocale(const std::string& locale, // means text such as "Google Chrome foo bar..." will be layed out LTR even // if "foo bar" is RTL. So this function prepends the necessary RLM in such // cases. -void AdjustParagraphDirectionality(base::string16* paragraph) { +void AdjustParagraphDirectionality(std::u16string* paragraph) { #if defined(OS_POSIX) && !defined(OS_APPLE) && !defined(OS_ANDROID) if (base::i18n::IsRTL() && base::i18n::StringContainsStrongRTLChars(*paragraph)) { - paragraph->insert(0, 1, - static_cast(base::i18n::kRightToLeftMark)); + paragraph->insert(0, 1, char16_t{base::i18n::kRightToLeftMark}); } #endif } @@ -579,7 +577,7 @@ std::string GetApplicationLocale(const std::string& pref_locale) { bool IsLocaleNameTranslated(const char* locale, const std::string& display_locale) { - base::string16 display_name = + std::u16string display_name = l10n_util::GetDisplayNameForLocale(locale, display_locale, false); // Because ICU sets the error code to U_USING_DEFAULT_WARNING whether or not // uloc_getDisplayName returns the actual translation or the default @@ -591,7 +589,7 @@ bool IsLocaleNameTranslated(const char* locale, base::UTF16ToASCII(display_name) != locale; } -base::string16 GetDisplayNameForLocale(const std::string& locale, +std::u16string GetDisplayNameForLocale(const std::string& locale, const std::string& display_locale, bool is_for_ui, bool disallow_default) { @@ -610,7 +608,7 @@ base::string16 GetDisplayNameForLocale(const std::string& locale, else if (locale_code == "mo") locale_code = "ro-MD"; - base::string16 display_name; + std::u16string display_name; #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. @@ -635,16 +633,14 @@ base::string16 GetDisplayNameForLocale(const std::string& locale, if (locale_code[0] == '-' || locale_code[0] == '_') { actual_size = uloc_getDisplayCountry( locale_code.c_str(), display_locale.c_str(), - base::i18n::ToUCharPtr(base::WriteInto(&display_name, kBufferSize)), - kBufferSize - 1, &error); + base::WriteInto(&display_name, kBufferSize), kBufferSize - 1, &error); } else { actual_size = uloc_getDisplayName( locale_code.c_str(), display_locale.c_str(), - base::i18n::ToUCharPtr(base::WriteInto(&display_name, kBufferSize)), - kBufferSize - 1, &error); + base::WriteInto(&display_name, kBufferSize), kBufferSize - 1, &error); } if (disallow_default && U_USING_DEFAULT_WARNING == error) - return base::string16(); + return std::u16string(); DCHECK(U_SUCCESS(error)); display_name.resize(actual_size); } @@ -656,7 +652,7 @@ base::string16 GetDisplayNameForLocale(const std::string& locale, return display_name; } -base::string16 GetDisplayNameForCountry(const std::string& country_code, +std::u16string GetDisplayNameForCountry(const std::string& country_code, const std::string& display_locale) { return GetDisplayNameForLocale("_" + country_code, display_locale, false); } @@ -756,24 +752,17 @@ std::string GetStringUTF8(int message_id) { return base::UTF16ToUTF8(GetStringUTF16(message_id)); } -base::string16 GetStringUTF16(int message_id) { +std::u16string GetStringUTF16(int message_id) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - base::string16 str = rb.GetLocalizedString(message_id); + std::u16string str = rb.GetLocalizedString(message_id); AdjustParagraphDirectionality(&str); return str; } -base::string16 GetStringFUTF16(int message_id, - const std::vector& replacements, - std::vector* offsets) { - // TODO(tc): We could save a string copy if we got the raw string as - // a StringPiece and were able to call ReplaceStringPlaceholders with - // a StringPiece format string and base::string16 substitution strings. In - // practice, the strings should be relatively short. - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - const base::string16& format_string = rb.GetLocalizedString(message_id); - +std::u16string FormatString(const std::u16string& format_string, + const std::vector& replacements, + std::vector* offsets) { #if DCHECK_IS_ON() // Make sure every replacement string is being used, so we don't just // silently fail to insert one. If |offsets| is non-NULL, then don't do this @@ -784,7 +773,7 @@ base::string16 GetStringFUTF16(int message_id, for (size_t i = 0; i < 9; ++i) { bool placeholder_should_exist = replacements.size() > i; - base::string16 placeholder = base::ASCIIToUTF16("$"); + std::u16string placeholder = u"$"; placeholder += (L'1' + i); size_t pos = format_string.find(placeholder); if (placeholder_should_exist) { @@ -800,107 +789,117 @@ base::string16 GetStringFUTF16(int message_id, } #endif - base::string16 formatted = base::ReplaceStringPlaceholders( - format_string, replacements, offsets); + std::u16string formatted = + base::ReplaceStringPlaceholders(format_string, replacements, offsets); AdjustParagraphDirectionality(&formatted); return formatted; } -std::string GetStringFUTF8(int message_id, - const base::string16& a) { +std::u16string GetStringFUTF16(int message_id, + const std::vector& replacements, + std::vector* offsets) { + // TODO(tc): We could save a string copy if we got the raw string as + // a StringPiece and were able to call ReplaceStringPlaceholders with + // a StringPiece format string and std::u16string substitution strings. In + // practice, the strings should be relatively short. + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + const std::u16string& format_string = rb.GetLocalizedString(message_id); + return FormatString(format_string, replacements, offsets); +} + +std::string GetStringFUTF8(int message_id, const std::u16string& a) { return base::UTF16ToUTF8(GetStringFUTF16(message_id, a)); } std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b) { + const std::u16string& a, + const std::u16string& b) { return base::UTF16ToUTF8(GetStringFUTF16(message_id, a, b)); } std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c) { return base::UTF16ToUTF8(GetStringFUTF16(message_id, a, b, c)); } std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d) { return base::UTF16ToUTF8(GetStringFUTF16(message_id, a, b, c, d)); } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a) { - std::vector replacements = {a}; +std::u16string GetStringFUTF16(int message_id, const std::u16string& a) { + std::vector replacements = {a}; return GetStringFUTF16(message_id, replacements, nullptr); } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b) { +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b) { return GetStringFUTF16(message_id, a, b, nullptr); } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c) { - std::vector replacements = {a, b, c}; +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, + const std::u16string& c) { + std::vector replacements = {a, b, c}; return GetStringFUTF16(message_id, replacements, nullptr); } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d) { - std::vector replacements = {a, b, c, d}; +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d) { + std::vector replacements = {a, b, c, d}; return GetStringFUTF16(message_id, replacements, nullptr); } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d, - const base::string16& e) { - std::vector replacements = {a, b, c, d, e}; +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d, + const std::u16string& e) { + std::vector replacements = {a, b, c, d, e}; return GetStringFUTF16(message_id, replacements, nullptr); } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, size_t* offset) { DCHECK(offset); std::vector offsets; - std::vector replacements = {a}; - base::string16 result = GetStringFUTF16(message_id, replacements, &offsets); + std::vector replacements = {a}; + std::u16string result = GetStringFUTF16(message_id, replacements, &offsets); DCHECK_EQ(1u, offsets.size()); *offset = offsets[0]; return result; } -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, std::vector* offsets) { - std::vector replacements = {a, b}; + std::vector replacements = {a, b}; return GetStringFUTF16(message_id, replacements, offsets); } -base::string16 GetStringFUTF16Int(int message_id, int a) { +std::u16string GetStringFUTF16Int(int message_id, int a) { return GetStringFUTF16(message_id, base::FormatNumber(a)); } -base::string16 GetStringFUTF16Int(int message_id, int64_t a) { +std::u16string GetStringFUTF16Int(int message_id, int64_t a) { return GetStringFUTF16(message_id, base::FormatNumber(a)); } -base::string16 GetPluralStringFUTF16(int message_id, int number) { +std::u16string GetPluralStringFUTF16(int message_id, int number) { return base::i18n::MessageFormatter::FormatWithNumberedArgs( GetStringUTF16(message_id), number); } @@ -909,14 +908,14 @@ std::string GetPluralStringFUTF8(int message_id, int number) { return base::UTF16ToUTF8(GetPluralStringFUTF16(message_id, number)); } -base::string16 GetSingleOrMultipleStringUTF16(int message_id, - bool is_multiple) { +std::u16string GetSingleOrMultipleStringUTF16(int message_id, + bool is_multiple) { return base::i18n::MessageFormatter::FormatWithNumberedArgs( GetStringUTF16(message_id), is_multiple ? "multiple" : "single"); } void SortStrings16(const std::string& locale, - std::vector* strings) { + std::vector* strings) { SortVectorWithStringKey(locale, strings, false); } diff --git a/chromium/ui/base/l10n/l10n_util.h b/chromium/ui/base/l10n/l10n_util.h index 5ebdb2e16a0..ebf572e393b 100644 --- a/chromium/ui/base/l10n/l10n_util.h +++ b/chromium/ui/base/l10n/l10n_util.h @@ -15,7 +15,6 @@ #include #include "base/component_export.h" -#include "base/strings/string16.h" #include "build/build_config.h" #if defined(OS_APPLE) @@ -77,14 +76,14 @@ bool IsLocaleNameTranslated(const char* locale, // If |is_for_ui| is true, U+200F is appended so that it can be // rendered properly in a RTL Chrome. COMPONENT_EXPORT(UI_BASE) -base::string16 GetDisplayNameForLocale(const std::string& locale, +std::u16string GetDisplayNameForLocale(const std::string& locale, const std::string& display_locale, bool is_for_ui, bool disallow_default = false); // Returns the display name of the |country_code| in |display_locale|. COMPONENT_EXPORT(UI_BASE) -base::string16 GetDisplayNameForCountry(const std::string& country_code, +std::u16string GetDisplayNameForCountry(const std::string& country_code, const std::string& display_locale); // Converts all - into _, to be consistent with ICU and file system names. @@ -114,72 +113,81 @@ COMPONENT_EXPORT(UI_BASE) bool IsValidLocaleSyntax(const std::string& locale); // Pulls resource string from the string bundle and returns it. COMPONENT_EXPORT(UI_BASE) std::string GetStringUTF8(int message_id); -COMPONENT_EXPORT(UI_BASE) base::string16 GetStringUTF16(int message_id); +COMPONENT_EXPORT(UI_BASE) std::u16string GetStringUTF16(int message_id); + +// Given a format string, replace $i with replacements[i] for all +// i < replacements.size(). Additionally, $$ is replaced by $. +// If non-NULL |offsets| will be replaced with the start points of the replaced +// strings. +COMPONENT_EXPORT(UI_BASE) +std::u16string FormatString(const std::u16string& format_string, + const std::vector& replacements, + std::vector* offsets); // Get a resource string and replace $i with replacements[i] for all // i < replacements.size(). Additionally, $$ is replaced by $. // If non-NULL |offsets| will be replaced with the start points of the replaced // strings. COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const std::vector& replacements, +std::u16string GetStringFUTF16(int message_id, + const std::vector& replacements, std::vector* offsets); // Convenience wrappers for the above. COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, const base::string16& a); +std::u16string GetStringFUTF16(int message_id, const std::u16string& a); COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b); +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b); COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, + const std::u16string& c); COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d); COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d, - const base::string16& e); +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d, + const std::u16string& e); COMPONENT_EXPORT(UI_BASE) -std::string GetStringFUTF8(int message_id, const base::string16& a); +std::string GetStringFUTF8(int message_id, const std::u16string& a); COMPONENT_EXPORT(UI_BASE) std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b); + const std::u16string& a, + const std::u16string& b); COMPONENT_EXPORT(UI_BASE) std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c); COMPONENT_EXPORT(UI_BASE) std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d); // Variants that return the offset(s) of the replaced parameters. The // vector based version returns offsets ordered by parameter. For example if // invoked with a and b offsets[0] gives the offset for a and offsets[1] the // offset of b regardless of where the parameters end up in the string. COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, size_t* offset); COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, +std::u16string GetStringFUTF16(int message_id, + const std::u16string& a, + const std::u16string& b, std::vector* offsets); // Convenience functions to get a string with a single integer as a parameter. @@ -194,8 +202,8 @@ base::string16 GetStringFUTF16(int message_id, // base::{Int*,Double}ToString convert a number to a string with // ASCII digits in non-UI strings. COMPONENT_EXPORT(UI_BASE) -base::string16 GetStringFUTF16Int(int message_id, int a); -base::string16 GetStringFUTF16Int(int message_id, int64_t a); +std::u16string GetStringFUTF16Int(int message_id, int a); +std::u16string GetStringFUTF16Int(int message_id, int64_t a); // Convenience functions to format a string with a single number that requires // plural formatting. Note that a simple 2-way rule (singular vs plural) @@ -209,7 +217,7 @@ base::string16 GetStringFUTF16Int(int message_id, int64_t a); // at 3 MB/s."), use base::i18n::MessageFormatter. // message_format_unittests.cc also has more examples of plural formatting. COMPONENT_EXPORT(UI_BASE) -base::string16 GetPluralStringFUTF16(int message_id, int number); +std::u16string GetPluralStringFUTF16(int message_id, int number); COMPONENT_EXPORT(UI_BASE) std::string GetPluralStringFUTF8(int message_id, int number); @@ -218,13 +226,13 @@ std::string GetPluralStringFUTF8(int message_id, int number); // (see the references above for Plural) with 'single', 'multiple', and // 'other' (fallback) instead of 'male', 'female', and 'other' (fallback). COMPONENT_EXPORT(UI_BASE) -base::string16 GetSingleOrMultipleStringUTF16(int message_id, bool is_multiple); +std::u16string GetSingleOrMultipleStringUTF16(int message_id, bool is_multiple); -// In place sorting of base::string16 strings using collation rules for +// In place sorting of std::u16string strings using collation rules for // |locale|. COMPONENT_EXPORT(UI_BASE) void SortStrings16(const std::string& locale, - std::vector* strings); + std::vector* strings); // Returns a vector of available locale codes from ICU. E.g., a vector // containing en-US, es, fr, fi, pt-PT, pt-BR, etc. diff --git a/chromium/ui/base/l10n/l10n_util_android.cc b/chromium/ui/base/l10n/l10n_util_android.cc index 4a509dfd3da..aad8c160880 100644 --- a/chromium/ui/base/l10n/l10n_util_android.cc +++ b/chromium/ui/base/l10n/l10n_util_android.cc @@ -80,7 +80,7 @@ ScopedJavaLocalRef JNI_LocalizationUtils_NewJavaLocale( } // namespace -base::string16 GetDisplayNameForLocale(const std::string& locale, +std::u16string GetDisplayNameForLocale(const std::string& locale, const std::string& display_locale) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef java_locale = diff --git a/chromium/ui/base/l10n/l10n_util_android.h b/chromium/ui/base/l10n/l10n_util_android.h index 23fd7b1a937..c0d32f3da1c 100644 --- a/chromium/ui/base/l10n/l10n_util_android.h +++ b/chromium/ui/base/l10n/l10n_util_android.h @@ -10,12 +10,11 @@ #include #include "base/component_export.h" -#include "base/strings/string16.h" namespace l10n_util { COMPONENT_EXPORT(UI_BASE) -base::string16 GetDisplayNameForLocale(const std::string& locale, +std::u16string GetDisplayNameForLocale(const std::string& locale, const std::string& display_locale); COMPONENT_EXPORT(UI_BASE) bool IsLayoutRtl(); diff --git a/chromium/ui/base/l10n/l10n_util_collator.h b/chromium/ui/base/l10n/l10n_util_collator.h index a6ac539ccfd..581327bd1e8 100644 --- a/chromium/ui/base/l10n/l10n_util_collator.h +++ b/chromium/ui/base/l10n/l10n_util_collator.h @@ -82,7 +82,7 @@ void SortStringsUsingMethod(const std::string& locale, // Compares two elements' string keys and returns true if the first element's // string key is less than the second element's string key. The Element must // have a method like the follow format to return the string key. -// const base::string16& GetStringKey() const; +// const std::u16string& GetStringKey() const; // This uses the locale specified in the constructor. template class StringComparator { @@ -92,10 +92,10 @@ class StringComparator { // Returns true if lhs precedes rhs. bool operator()(const Element& lhs, const Element& rhs) const { - const base::string16& lhs_string_key = lhs.GetStringKey(); - const base::string16& rhs_string_key = rhs.GetStringKey(); + const std::u16string& lhs_string_key = lhs.GetStringKey(); + const std::u16string& rhs_string_key = rhs.GetStringKey(); - return StringComparator(collator_)(lhs_string_key, + return StringComparator(collator_)(lhs_string_key, rhs_string_key); } @@ -103,12 +103,12 @@ class StringComparator { icu::Collator* collator_; }; -// Specialization of operator() method for base::string16 version. +// Specialization of operator() method for std::u16string version. template <> COMPONENT_EXPORT(UI_BASE) -inline bool StringComparator::operator()( - const base::string16& lhs, - const base::string16& rhs) const { +inline bool StringComparator::operator()( + const std::u16string& lhs, + const std::u16string& rhs) const { // If we can not get collator instance for specified locale, just do simple // string compare. if (!collator_) diff --git a/chromium/ui/base/l10n/l10n_util_mac.h b/chromium/ui/base/l10n/l10n_util_mac.h index 0d9cb8683b3..17b8e65005b 100644 --- a/chromium/ui/base/l10n/l10n_util_mac.h +++ b/chromium/ui/base/l10n/l10n_util_mac.h @@ -11,7 +11,6 @@ #include #include "base/component_export.h" -#include "base/strings/string16.h" #ifdef __OBJC__ @class NSString; @@ -28,14 +27,14 @@ namespace l10n_util { // "$lowercase_language ($UPPERCASE_SCRIPT)". If the - token is not found, the // lowercase version of |locale| will be returned. COMPONENT_EXPORT(UI_BASE) -base::string16 GetDisplayNameForLocale(const std::string& locale, +std::u16string GetDisplayNameForLocale(const std::string& locale, const std::string& display_locale); // Remove the Windows-style accelerator marker (for labels, menuitems, etc.) // and change "..." into an ellipsis. // Returns the result in an autoreleased NSString. COMPONENT_EXPORT(UI_BASE) -NSString* FixUpWindowsStyleLabel(const base::string16& label); +NSString* FixUpWindowsStyleLabel(const std::u16string& label); // Pulls resource string from the string bundle and returns it. COMPONENT_EXPORT(UI_BASE) NSString* GetNSString(int message_id); @@ -43,36 +42,36 @@ COMPONENT_EXPORT(UI_BASE) NSString* GetNSString(int message_id); // Get a resource string and replace $1-$2-$3 with |a| and |b| // respectively. Additionally, $$ is replaced by $. COMPONENT_EXPORT(UI_BASE) -NSString* GetNSStringF(int message_id, const base::string16& a); +NSString* GetNSStringF(int message_id, const std::u16string& a); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b); + const std::u16string& a, + const std::u16string& b); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d, - const base::string16& e); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d, + const std::u16string& e); // Variants that return the offset(s) of the replaced parameters. (See // app/l10n_util.h for more details.) COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, + const std::u16string& a, + const std::u16string& b, std::vector* offsets); // Same as GetNSString, but runs the result through FixUpWindowsStyleLabel @@ -82,22 +81,22 @@ COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringWithFixup(int message_id); // Same as GetNSStringF, but runs the result through FixUpWindowsStyleLabel // before returning it. COMPONENT_EXPORT(UI_BASE) -NSString* GetNSStringFWithFixup(int message_id, const base::string16& a); +NSString* GetNSStringFWithFixup(int message_id, const std::u16string& a); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b); + const std::u16string& a, + const std::u16string& b); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c); COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d); // Get a resource string using |number| with a locale-specific plural rule. // |message_id| points to a message in the ICU syntax. diff --git a/chromium/ui/base/l10n/l10n_util_mac.mm b/chromium/ui/base/l10n/l10n_util_mac.mm index 5fd261bd54f..b1dfef6a9a5 100644 --- a/chromium/ui/base/l10n/l10n_util_mac.mm +++ b/chromium/ui/base/l10n/l10n_util_mac.mm @@ -23,7 +23,7 @@ base::LazyInstance>::DestructorAtExit namespace l10n_util { -base::string16 GetDisplayNameForLocale(const std::string& locale, +std::u16string GetDisplayNameForLocale(const std::string& locale, const std::string& display_locale) { NSString* display = base::SysUTF8ToNSString(display_locale); @@ -93,13 +93,13 @@ void OverrideLocaleWithCocoaLocale() { // Remove the Windows-style accelerator marker and change "..." into an // ellipsis. Returns the result in an autoreleased NSString. -NSString* FixUpWindowsStyleLabel(const base::string16& label) { - const base::char16 kEllipsisUTF16 = 0x2026; - base::string16 ret; +NSString* FixUpWindowsStyleLabel(const std::u16string& label) { + const char16_t kEllipsisUTF16 = 0x2026; + std::u16string ret; size_t label_len = label.length(); ret.reserve(label_len); for (size_t i = 0; i < label_len; ++i) { - base::char16 c = label[i]; + char16_t c = label[i]; if (c == '(' && i + 3 < label_len && label[i + 1] == '&' && label[i + 3] == ')') { // Strip '(&?)' patterns which means Windows-style accelerator in some @@ -126,49 +126,48 @@ NSString* GetNSString(int message_id) { return base::SysUTF16ToNSString(l10n_util::GetStringUTF16(message_id)); } -NSString* GetNSStringF(int message_id, - const base::string16& a) { +NSString* GetNSStringF(int message_id, const std::u16string& a) { return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, a)); } NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b) { + const std::u16string& a, + const std::u16string& b) { return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, a, b)); } NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c) { return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, a, b, c)); } NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d) { return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, a, b, c, d)); } NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d, - const base::string16& e) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d, + const std::u16string& e) { return base::SysUTF16ToNSString( l10n_util::GetStringFUTF16(message_id, a, b, c, d, e)); } NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, + const std::u16string& a, + const std::u16string& b, std::vector* offsets) { return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(message_id, a, b, offsets)); @@ -178,32 +177,31 @@ NSString* GetNSStringWithFixup(int message_id) { return FixUpWindowsStyleLabel(l10n_util::GetStringUTF16(message_id)); } -NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a) { +NSString* GetNSStringFWithFixup(int message_id, const std::u16string& a) { return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, a)); } NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b) { + const std::u16string& a, + const std::u16string& b) { return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, a, b)); } NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c) { return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, a, b, c)); } NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d) { + const std::u16string& a, + const std::u16string& b, + const std::u16string& c, + const std::u16string& d) { return FixUpWindowsStyleLabel(l10n_util::GetStringFUTF16(message_id, a, b, c, d)); } diff --git a/chromium/ui/base/l10n/l10n_util_mac_unittest.mm b/chromium/ui/base/l10n/l10n_util_mac_unittest.mm index 4ae224c0365..9b2802415f5 100644 --- a/chromium/ui/base/l10n/l10n_util_mac_unittest.mm +++ b/chromium/ui/base/l10n/l10n_util_mac_unittest.mm @@ -39,7 +39,7 @@ TEST_F(L10nUtilMacTest, FixUpWindowsStyleLabel) { { @"(&b)foo", @"foo" }, }; for (size_t idx = 0; idx < base::size(data); ++idx) { - base::string16 input16(base::SysNSStringToUTF16(data[idx].input)); + std::u16string input16(base::SysNSStringToUTF16(data[idx].input)); NSString* result = l10n_util::FixUpWindowsStyleLabel(input16); EXPECT_TRUE(result != nil) << "Fixup Failed, idx = " << idx; @@ -52,7 +52,7 @@ TEST_F(L10nUtilMacTest, FixUpWindowsStyleLabel) { TEST_F(L10nUtilMacTest, GetDisplayNameForLocale) { // Test documented error cases and return values of GetDisplayNameForLocale. - base::string16 result = l10n_util::GetDisplayNameForLocale("xyz", "en"); + std::u16string result = l10n_util::GetDisplayNameForLocale("xyz", "en"); EXPECT_EQ(base::SysNSStringToUTF16(@"xyz"), result); result = l10n_util::GetDisplayNameForLocale("Xyz", "en"); diff --git a/chromium/ui/base/l10n/l10n_util_unittest.cc b/chromium/ui/base/l10n/l10n_util_unittest.cc index 4b7b3406557..100e40fe785 100644 --- a/chromium/ui/base/l10n/l10n_util_unittest.cc +++ b/chromium/ui/base/l10n/l10n_util_unittest.cc @@ -41,11 +41,11 @@ namespace { class StringWrapper { public: - explicit StringWrapper(const base::string16& string) : string_(string) {} - const base::string16& string() const { return string_; } + explicit StringWrapper(const std::u16string& string) : string_(string) {} + const std::u16string& string() const { return string_; } private: - base::string16 string_; + std::u16string string_; DISALLOW_COPY_AND_ASSIGN(StringWrapper); }; @@ -59,16 +59,14 @@ TEST_F(L10nUtilTest, GetString) { std::string s = l10n_util::GetStringUTF8(IDS_SIMPLE); EXPECT_EQ(std::string("Hello World!"), s); - s = l10n_util::GetStringFUTF8(IDS_PLACEHOLDERS, - UTF8ToUTF16("chrome"), - UTF8ToUTF16("10")); + s = l10n_util::GetStringFUTF8(IDS_PLACEHOLDERS, u"chrome", u"10"); EXPECT_EQ(std::string("Hello, chrome. Your number is 10."), s); - base::string16 s16 = l10n_util::GetStringFUTF16Int(IDS_PLACEHOLDERS_2, 20); + std::u16string s16 = l10n_util::GetStringFUTF16Int(IDS_PLACEHOLDERS_2, 20); // Consecutive '$' characters override any placeholder functionality. // See //base/strings/string_util.h ReplaceStringPlaceholders(). - EXPECT_EQ(UTF8ToUTF16("You owe me $$1."), s16); + EXPECT_EQ(u"You owe me $$1.", s16); } #if !defined(OS_APPLE) && !defined(OS_ANDROID) @@ -387,17 +385,17 @@ TEST_F(L10nUtilTest, GetAppLocale) { TEST_F(L10nUtilTest, SortStringsUsingFunction) { std::vector> strings; - strings.push_back(std::make_unique(UTF8ToUTF16("C"))); - strings.push_back(std::make_unique(UTF8ToUTF16("d"))); - strings.push_back(std::make_unique(UTF8ToUTF16("b"))); - strings.push_back(std::make_unique(UTF8ToUTF16("a"))); + strings.push_back(std::make_unique(u"C")); + strings.push_back(std::make_unique(u"d")); + strings.push_back(std::make_unique(u"b")); + strings.push_back(std::make_unique(u"a")); l10n_util::SortStringsUsingMethod("en-US", &strings, &StringWrapper::string); - ASSERT_TRUE(UTF8ToUTF16("a") == strings[0]->string()); - ASSERT_TRUE(UTF8ToUTF16("b") == strings[1]->string()); - ASSERT_TRUE(UTF8ToUTF16("C") == strings[2]->string()); - ASSERT_TRUE(UTF8ToUTF16("d") == strings[3]->string()); + ASSERT_TRUE(u"a" == strings[0]->string()); + ASSERT_TRUE(u"b" == strings[1]->string()); + ASSERT_TRUE(u"C" == strings[2]->string()); + ASSERT_TRUE(u"d" == strings[3]->string()); } /** @@ -408,13 +406,13 @@ void CheckUiDisplayNameForLocale(const std::string& locale, const std::string& display_locale, bool is_rtl) { EXPECT_EQ(true, base::i18n::IsRTL()); - base::string16 result = l10n_util::GetDisplayNameForLocale(locale, - display_locale, - /* is_for_ui */ true); + std::u16string result = + l10n_util::GetDisplayNameForLocale(locale, display_locale, + /* is_for_ui */ true); bool rtl_direction = true; for (size_t i = 0; i < result.length() - 1; i++) { - base::char16 ch = result.at(i); + char16_t ch = result.at(i); switch (ch) { case base::i18n::kLeftToRightMark: case base::i18n::kLeftToRightEmbeddingMark: @@ -436,7 +434,7 @@ TEST_F(L10nUtilTest, GetDisplayNameForLocale) { // Test zh-CN and zh-TW are treated as zh-Hans and zh-Hant. // Displays as "Chinese, Simplified" on iOS 13+ and as "Chinese (Simplified)" // on other platforms. - base::string16 result = + std::u16string result = l10n_util::GetDisplayNameForLocale("zh-CN", "en", false); EXPECT_TRUE( base::MatchPattern(base::UTF16ToUTF8(result), "Chinese*Simplified*")); @@ -453,25 +451,25 @@ TEST_F(L10nUtilTest, GetDisplayNameForLocale) { EXPECT_EQ(l10n_util::GetDisplayNameForLocale("fil", "en", false), result); result = l10n_util::GetDisplayNameForLocale("pt-BR", "en", false); - EXPECT_EQ(ASCIIToUTF16("Portuguese (Brazil)"), result); + EXPECT_EQ(u"Portuguese (Brazil)", result); result = l10n_util::GetDisplayNameForLocale("es-419", "en", false); - EXPECT_EQ(ASCIIToUTF16("Spanish (Latin America)"), result); + EXPECT_EQ(u"Spanish (Latin America)", result); result = l10n_util::GetDisplayNameForLocale("mo", "en", false); EXPECT_EQ(l10n_util::GetDisplayNameForLocale("ro-MD", "en", false), result); result = l10n_util::GetDisplayNameForLocale("-BR", "en", false); - EXPECT_EQ(ASCIIToUTF16("Brazil"), result); + EXPECT_EQ(u"Brazil", result); result = l10n_util::GetDisplayNameForLocale("xyz-xyz", "en", false); - EXPECT_EQ(ASCIIToUTF16("xyz (XYZ)"), result); + EXPECT_EQ(u"xyz (XYZ)", result); // Make sure that en-GB locale has the corect display names. result = l10n_util::GetDisplayNameForLocale("en", "en-GB", false); - EXPECT_EQ(ASCIIToUTF16("English"), result); + EXPECT_EQ(u"English", result); result = l10n_util::GetDisplayNameForLocale("es-419", "en-GB", false); - EXPECT_EQ(ASCIIToUTF16("Spanish (Latin America)"), result); + EXPECT_EQ(u"Spanish (Latin America)", result); // Check for directional markers when using RTL languages to ensure that // direction neutral characters such as parentheses are properly formatted. @@ -488,29 +486,29 @@ TEST_F(L10nUtilTest, GetDisplayNameForLocale) { // ToUpper and ToLower should work with embedded NULLs. const size_t length_with_null = 4; - base::char16 buf_with_null[length_with_null] = { 0, 'a', 0, 'b' }; - base::string16 string16_with_null(buf_with_null, length_with_null); + char16_t buf_with_null[length_with_null] = {0, 'a', 0, 'b'}; + std::u16string string16_with_null(buf_with_null, length_with_null); - base::string16 upper_with_null = base::i18n::ToUpper(string16_with_null); + std::u16string upper_with_null = base::i18n::ToUpper(string16_with_null); ASSERT_EQ(length_with_null, upper_with_null.size()); EXPECT_TRUE(upper_with_null[0] == 0 && upper_with_null[1] == 'A' && upper_with_null[2] == 0 && upper_with_null[3] == 'B'); - base::string16 lower_with_null = base::i18n::ToLower(upper_with_null); + std::u16string lower_with_null = base::i18n::ToLower(upper_with_null); ASSERT_EQ(length_with_null, upper_with_null.size()); EXPECT_TRUE(lower_with_null[0] == 0 && lower_with_null[1] == 'a' && lower_with_null[2] == 0 && lower_with_null[3] == 'b'); } TEST_F(L10nUtilTest, GetDisplayNameForCountry) { - base::string16 result = l10n_util::GetDisplayNameForCountry("BR", "en"); - EXPECT_EQ(ASCIIToUTF16("Brazil"), result); + std::u16string result = l10n_util::GetDisplayNameForCountry("BR", "en"); + EXPECT_EQ(u"Brazil", result); result = l10n_util::GetDisplayNameForCountry("419", "en"); - EXPECT_EQ(ASCIIToUTF16("Latin America"), result); + EXPECT_EQ(u"Latin America", result); result = l10n_util::GetDisplayNameForCountry("xyz", "en"); - EXPECT_EQ(ASCIIToUTF16("XYZ"), result); + EXPECT_EQ(u"XYZ", result); } TEST_F(L10nUtilTest, GetParentLocales) { @@ -587,7 +585,7 @@ TEST_F(L10nUtilTest, TimeDurationFormatAllLocales) { base::TimeDelta kDelta = base::TimeDelta::FromMinutes(15 * 60 + 42); for (const std::string& locale : l10n_util::GetAvailableICULocales()) { base::i18n::SetICUDefaultLocale(locale); - base::string16 str; + std::u16string str; const bool result = base::TimeDurationFormat(kDelta, base::DURATION_WIDTH_NUMERIC, &str); EXPECT_TRUE(result) << "Failed to format duration for " << locale; diff --git a/chromium/ui/base/l10n/time_format.cc b/chromium/ui/base/l10n/time_format.cc index 4316a212ba0..2024f7b8ec1 100644 --- a/chromium/ui/base/l10n/time_format.cc +++ b/chromium/ui/base/l10n/time_format.cc @@ -8,7 +8,6 @@ #include "base/check_op.h" #include "base/component_export.h" -#include "base/i18n/uchar.h" #include "base/lazy_instance.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" @@ -29,13 +28,13 @@ base::LazyInstance::Leaky g_container = LAZY_INSTANCE_INITIALIZER; // static -base::string16 TimeFormat::Simple(TimeFormat::Format format, +std::u16string TimeFormat::Simple(TimeFormat::Format format, TimeFormat::Length length, const base::TimeDelta& delta) { return Detailed(format, length, 0, delta); } -base::string16 TimeFormat::SimpleWithMonthAndYear(TimeFormat::Format format, +std::u16string TimeFormat::SimpleWithMonthAndYear(TimeFormat::Format format, TimeFormat::Length length, const base::TimeDelta& delta, bool with_month_and_year) { @@ -44,14 +43,14 @@ base::string16 TimeFormat::SimpleWithMonthAndYear(TimeFormat::Format format, } // static -base::string16 TimeFormat::Detailed(TimeFormat::Format format, +std::u16string TimeFormat::Detailed(TimeFormat::Format format, TimeFormat::Length length, int cutoff, const base::TimeDelta& delta) { return DetailedWithMonthAndYear(format, length, cutoff, delta, false); } -base::string16 TimeFormat::DetailedWithMonthAndYear( +std::u16string TimeFormat::DetailedWithMonthAndYear( TimeFormat::Format format, TimeFormat::Length length, int cutoff, @@ -143,17 +142,15 @@ base::string16 TimeFormat::DetailedWithMonthAndYear( const int capacity = time_string.length() + 1; DCHECK_GT(capacity, 1); - base::string16 result; + std::u16string result; UErrorCode error = U_ZERO_ERROR; - time_string.extract( - base::i18n::ToUCharPtr(base::WriteInto(&result, capacity)), capacity, - error); + time_string.extract(base::WriteInto(&result, capacity), capacity, error); DCHECK(U_SUCCESS(error)); return result; } // static -base::string16 TimeFormat::RelativeDate( +std::u16string TimeFormat::RelativeDate( const base::Time& time, const base::Time* optional_midnight_today) { const base::Time midnight_today = optional_midnight_today @@ -163,12 +160,12 @@ base::string16 TimeFormat::RelativeDate( const base::Time tomorrow = midnight_today + kDay; const base::Time yesterday = midnight_today - kDay; if (time >= tomorrow) - return base::string16(); + return std::u16string(); if (time >= midnight_today) return l10n_util::GetStringUTF16(IDS_PAST_TIME_TODAY); return (time >= yesterday) ? l10n_util::GetStringUTF16(IDS_PAST_TIME_YESTERDAY) - : base::string16(); + : std::u16string(); } } // namespace ui diff --git a/chromium/ui/base/l10n/time_format.h b/chromium/ui/base/l10n/time_format.h index d1691441eb2..66533d58042 100644 --- a/chromium/ui/base/l10n/time_format.h +++ b/chromium/ui/base/l10n/time_format.h @@ -5,9 +5,10 @@ #ifndef UI_BASE_L10N_TIME_FORMAT_H_ #define UI_BASE_L10N_TIME_FORMAT_H_ +#include + #include "base/component_export.h" #include "base/macros.h" -#include "base/strings/string16.h" namespace base { class Time; @@ -33,7 +34,7 @@ class COMPONENT_EXPORT(UI_BASE) TimeFormat { }; // Equivalent to SimpleWithMonthAndYear(format, length, delta, false); - static base::string16 Simple(Format format, + static std::u16string Simple(Format format, Length length, const base::TimeDelta& delta); // Return a localized string of approximate time duration, formatted as a @@ -41,14 +42,14 @@ class COMPONENT_EXPORT(UI_BASE) TimeFormat { // of format and length are implemented. // If |use_month_and_year| is false. biggest unit is the day. If it is true, // "month" and "year" are also used. - static base::string16 SimpleWithMonthAndYear(Format format, + static std::u16string SimpleWithMonthAndYear(Format format, Length length, const base::TimeDelta& delta, bool use_month_and_year); // Equivalent to // DetailedWithMonthAndYear(format, length, cutoff, delta, false); - static base::string16 Detailed(Format format, + static std::u16string Detailed(Format format, Length length, int cutoff, const base::TimeDelta& delta); @@ -88,7 +89,7 @@ class COMPONENT_EXPORT(UI_BASE) TimeFormat { // units] and are concatenated after having been formatted individually. The // separator between first unit and second unit (a blank in English) is // included in IDS_TIME_*_1ST. - static base::string16 DetailedWithMonthAndYear(Format format, + static std::u16string DetailedWithMonthAndYear(Format format, Length length, int cutoff, const base::TimeDelta& delta, @@ -108,7 +109,7 @@ class COMPONENT_EXPORT(UI_BASE) TimeFormat { // If NULL, the current day's midnight will be retrieved, which can be // slow. If many items are being processed, it is best to get the current // time once at the beginning and pass it for each computation. - static base::string16 RelativeDate(const base::Time& time, + static std::u16string RelativeDate(const base::Time& time, const base::Time* optional_midnight_today); private: diff --git a/chromium/ui/base/l10n/time_format_unittest.cc b/chromium/ui/base/l10n/time_format_unittest.cc index 93dbe4a5ec3..1f522267c9f 100644 --- a/chromium/ui/base/l10n/time_format_unittest.cc +++ b/chromium/ui/base/l10n/time_format_unittest.cc @@ -4,8 +4,9 @@ #include "ui/base/l10n/time_format.h" +#include + #include "base/files/file_path.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" @@ -80,204 +81,236 @@ class TimeFormatTest : public ::testing::Test { protected: void TestStrings() { // Test English strings (simple, singular). - EXPECT_EQ(ASCIIToUTF16("1 sec"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1s_)); - EXPECT_EQ(ASCIIToUTF16("1 min"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1m_)); - EXPECT_EQ(ASCIIToUTF16("1 hour"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1h_)); - EXPECT_EQ(ASCIIToUTF16("1 day"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1d_)); - EXPECT_EQ(ASCIIToUTF16("1 second"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_1s_)); - EXPECT_EQ(ASCIIToUTF16("1 minute"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_1m_)); - EXPECT_EQ(ASCIIToUTF16("1 hour"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_1h_)); - EXPECT_EQ(ASCIIToUTF16("1 day"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_1d_)); - EXPECT_EQ(ASCIIToUTF16("1 month"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_DURATION, - TimeFormat::LENGTH_LONG, - delta_1mo_, true)); - EXPECT_EQ(ASCIIToUTF16("1 month"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_DURATION, - TimeFormat::LENGTH_LONG, - delta_1mo10d_, true)); - EXPECT_EQ(ASCIIToUTF16("1 year"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_DURATION, - TimeFormat::LENGTH_LONG, - delta_1y_, true)); - EXPECT_EQ(ASCIIToUTF16("1 sec left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_1s_)); - EXPECT_EQ(ASCIIToUTF16("1 min left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_1m_)); - EXPECT_EQ(ASCIIToUTF16("1 hour left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_1h_)); - EXPECT_EQ(ASCIIToUTF16("1 day left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_1d_)); - EXPECT_EQ(ASCIIToUTF16("1 second left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1s_)); - EXPECT_EQ(ASCIIToUTF16("1 minute left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1m_)); - EXPECT_EQ(ASCIIToUTF16("1 hour left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1h_)); - EXPECT_EQ(ASCIIToUTF16("1 day left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1d_)); - EXPECT_EQ(ASCIIToUTF16("1 month left"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_REMAINING, - TimeFormat::LENGTH_LONG, - delta_1mo_, true)); - EXPECT_EQ(ASCIIToUTF16("1 month left"), + EXPECT_EQ(u"1 sec", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1s_)); + EXPECT_EQ(u"1 min", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1m_)); + EXPECT_EQ(u"1 hour", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1h_)); + EXPECT_EQ(u"1 day", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1d_)); + EXPECT_EQ(u"1 second", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1s_)); + EXPECT_EQ(u"1 minute", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1m_)); + EXPECT_EQ(u"1 hour", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1h_)); + EXPECT_EQ(u"1 day", TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1d_)); + EXPECT_EQ(u"1 month", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1mo_, true)); + EXPECT_EQ(u"1 month", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1mo10d_, true)); + EXPECT_EQ(u"1 year", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_1y_, true)); + EXPECT_EQ(u"1 sec left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_1s_)); + EXPECT_EQ(u"1 min left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_1m_)); + EXPECT_EQ(u"1 hour left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_1h_)); + EXPECT_EQ(u"1 day left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_1d_)); + EXPECT_EQ(u"1 second left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_1s_)); + EXPECT_EQ(u"1 minute left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_1m_)); + EXPECT_EQ(u"1 hour left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_1h_)); + EXPECT_EQ(u"1 day left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_1d_)); + EXPECT_EQ(u"1 month left", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_1mo_, true)); + EXPECT_EQ(u"1 month left", TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1mo10d_, true)); - EXPECT_EQ(ASCIIToUTF16("1 year left"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_REMAINING, - TimeFormat::LENGTH_LONG, - delta_1y_, true)); - EXPECT_EQ(ASCIIToUTF16("1 sec ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_1s_)); - EXPECT_EQ(ASCIIToUTF16("1 min ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_1m_)); - EXPECT_EQ(ASCIIToUTF16("1 hour ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_1h_)); - EXPECT_EQ(ASCIIToUTF16("1 day ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_1d_)); - EXPECT_EQ(ASCIIToUTF16("1 month ago"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_ELAPSED, - TimeFormat::LENGTH_LONG, - delta_1mo_, true)); - EXPECT_EQ(ASCIIToUTF16("1 month ago"), + EXPECT_EQ(u"1 year left", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_1y_, true)); + EXPECT_EQ(u"1 sec ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_1s_)); + EXPECT_EQ(u"1 min ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_1m_)); + EXPECT_EQ(u"1 hour ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_1h_)); + EXPECT_EQ(u"1 day ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_1d_)); + EXPECT_EQ(u"1 month ago", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_LONG, delta_1mo_, true)); + EXPECT_EQ(u"1 month ago", TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1mo10d_, true)); - EXPECT_EQ(ASCIIToUTF16("1 year ago"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_ELAPSED, - TimeFormat::LENGTH_LONG, - delta_1y_, true)); - EXPECT_EQ(ASCIIToUTF16("1 second ago"), + EXPECT_EQ(u"1 year ago", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_LONG, delta_1y_, true)); + EXPECT_EQ(u"1 second ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1s_)); - EXPECT_EQ(ASCIIToUTF16("1 minute ago"), + EXPECT_EQ(u"1 minute ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1m_)); - EXPECT_EQ(ASCIIToUTF16("1 hour ago"), + EXPECT_EQ(u"1 hour ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1h_)); - EXPECT_EQ(ASCIIToUTF16("1 day ago"), + EXPECT_EQ(u"1 day ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1d_)); // Test English strings (simple, plural). - EXPECT_EQ(ASCIIToUTF16("2 secs"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_2s_)); - EXPECT_EQ(ASCIIToUTF16("2 mins"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_2d_)); - EXPECT_EQ(ASCIIToUTF16("2 seconds"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_2s_)); - EXPECT_EQ(ASCIIToUTF16("2 minutes"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_2d_)); - EXPECT_EQ(ASCIIToUTF16("30 days"), + EXPECT_EQ(u"2 secs", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_2s_)); + EXPECT_EQ(u"2 mins", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_2m_)); + EXPECT_EQ(u"2 hours", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_2h_)); + EXPECT_EQ(u"2 days", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_2d_)); + EXPECT_EQ(u"2 seconds", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_2s_)); + EXPECT_EQ(u"2 minutes", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_2m_)); + EXPECT_EQ(u"2 hours", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_2h_)); + EXPECT_EQ(u"2 days", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_2d_)); + EXPECT_EQ(u"30 days", TimeFormat::Simple(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_1mo_)); - EXPECT_EQ(ASCIIToUTF16("365 days"), + EXPECT_EQ(u"365 days", TimeFormat::Simple(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, delta_1y_)); - EXPECT_EQ(ASCIIToUTF16("2 months"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_DURATION, - TimeFormat::LENGTH_LONG, - delta_2mo_, true)); - EXPECT_EQ(ASCIIToUTF16("2 years"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_DURATION, - TimeFormat::LENGTH_LONG, - delta_2y_, true)); - EXPECT_EQ(ASCIIToUTF16("2 secs left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_2s_)); - EXPECT_EQ(ASCIIToUTF16("2 mins left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_SHORT, delta_2d_)); - EXPECT_EQ(ASCIIToUTF16("2 seconds left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_2s_)); - EXPECT_EQ(ASCIIToUTF16("2 minutes left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days left"), TimeFormat::Simple( - TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_2d_)); - EXPECT_EQ(ASCIIToUTF16("30 days left"), + EXPECT_EQ(u"2 months", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_2mo_, true)); + EXPECT_EQ(u"2 years", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, delta_2y_, true)); + EXPECT_EQ(u"2 secs left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_2s_)); + EXPECT_EQ(u"2 mins left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_2m_)); + EXPECT_EQ(u"2 hours left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_2h_)); + EXPECT_EQ(u"2 days left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_SHORT, delta_2d_)); + EXPECT_EQ(u"2 seconds left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_2s_)); + EXPECT_EQ(u"2 minutes left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_2m_)); + EXPECT_EQ(u"2 hours left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_2h_)); + EXPECT_EQ(u"2 days left", + TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_2d_)); + EXPECT_EQ(u"30 days left", TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1mo_)); - EXPECT_EQ(ASCIIToUTF16("365 days left"), + EXPECT_EQ(u"365 days left", TimeFormat::Simple(TimeFormat::FORMAT_REMAINING, TimeFormat::LENGTH_LONG, delta_1y_)); - EXPECT_EQ(ASCIIToUTF16("2 months left"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_REMAINING, - TimeFormat::LENGTH_LONG, - delta_2mo_, true)); - EXPECT_EQ(ASCIIToUTF16("2 years left"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_REMAINING, - TimeFormat::LENGTH_LONG, - delta_2y_, true)); - EXPECT_EQ(ASCIIToUTF16("2 secs ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_2s_)); - EXPECT_EQ(ASCIIToUTF16("2 mins ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days ago"), TimeFormat::Simple( - TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_2d_)); - EXPECT_EQ(ASCIIToUTF16("2 seconds ago"), + EXPECT_EQ(u"2 months left", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_2mo_, true)); + EXPECT_EQ(u"2 years left", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_REMAINING, + TimeFormat::LENGTH_LONG, delta_2y_, true)); + EXPECT_EQ(u"2 secs ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_2s_)); + EXPECT_EQ(u"2 mins ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_2m_)); + EXPECT_EQ(u"2 hours ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_2h_)); + EXPECT_EQ(u"2 days ago", + TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_SHORT, delta_2d_)); + EXPECT_EQ(u"2 seconds ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_2s_)); - EXPECT_EQ(ASCIIToUTF16("2 minutes ago"), + EXPECT_EQ(u"2 minutes ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours ago"), + EXPECT_EQ(u"2 hours ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days ago"), + EXPECT_EQ(u"2 days ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT, delta_2d_)); - EXPECT_EQ(ASCIIToUTF16("30 days ago"), + EXPECT_EQ(u"30 days ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1mo_)); - EXPECT_EQ(ASCIIToUTF16("365 days ago"), + EXPECT_EQ(u"365 days ago", TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, delta_1y_)); - EXPECT_EQ(ASCIIToUTF16("2 months ago"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_ELAPSED, - TimeFormat::LENGTH_LONG, - delta_2mo_, true)); - EXPECT_EQ(ASCIIToUTF16("2 years ago"), - TimeFormat::SimpleWithMonthAndYear(TimeFormat::FORMAT_ELAPSED, - TimeFormat::LENGTH_LONG, - delta_2y_, true)); + EXPECT_EQ(u"2 months ago", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_LONG, delta_2mo_, true)); + EXPECT_EQ(u"2 years ago", TimeFormat::SimpleWithMonthAndYear( + TimeFormat::FORMAT_ELAPSED, + TimeFormat::LENGTH_LONG, delta_2y_, true)); // Test English strings (detailed, singular and plural). - EXPECT_EQ(ASCIIToUTF16("1 minute and 2 seconds"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 3, delta_1m2s_)); - EXPECT_EQ(ASCIIToUTF16("2 minutes and 1 second"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 3, delta_2m1s_)); - EXPECT_EQ(ASCIIToUTF16("1 hour and 2 minutes"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 3, delta_1h2m_)); - EXPECT_EQ(ASCIIToUTF16("2 hours and 1 minute"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 3, delta_2h1m_)); - EXPECT_EQ(ASCIIToUTF16("1 day and 2 hours"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 3, delta_1d2h_)); - EXPECT_EQ(ASCIIToUTF16("2 days and 1 hour"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 3, delta_2d1h_)); + EXPECT_EQ(u"1 minute and 2 seconds", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 3, delta_1m2s_)); + EXPECT_EQ(u"2 minutes and 1 second", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 3, delta_2m1s_)); + EXPECT_EQ(u"1 hour and 2 minutes", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 3, delta_1h2m_)); + EXPECT_EQ(u"2 hours and 1 minute", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 3, delta_2h1m_)); + EXPECT_EQ(u"1 day and 2 hours", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 3, delta_1d2h_)); + EXPECT_EQ(u"2 days and 1 hour", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 3, delta_2d1h_)); } TimeDelta delta_0s_; @@ -335,95 +368,114 @@ class TimeFormatTest : public ::testing::Test { TEST_F(TimeFormatTest, SimpleAndDetailedRounding) { // Test rounding behavior (simple). - EXPECT_EQ(ASCIIToUTF16("0 secs"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_0s_)); - EXPECT_EQ(ASCIIToUTF16("0 secs"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 sec"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_500ms_)); - EXPECT_EQ(ASCIIToUTF16("1 sec"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1s499ms_)); - EXPECT_EQ(ASCIIToUTF16("2 secs"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1s500ms_)); - EXPECT_EQ(ASCIIToUTF16("59 secs"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_59s499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 min"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_59s500ms_)); - EXPECT_EQ(ASCIIToUTF16("1 min"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, - delta_1m29s999ms_)); - EXPECT_EQ(ASCIIToUTF16("2 mins"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1m30s_)); - EXPECT_EQ(ASCIIToUTF16("59 mins"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, - delta_59m29s999ms_)); - EXPECT_EQ(ASCIIToUTF16("1 hour"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_59m30s_)); - EXPECT_EQ(ASCIIToUTF16("1 hour"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, - delta_1h29m59s999ms_)); - EXPECT_EQ(ASCIIToUTF16("2 hours"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1h30m_)); - EXPECT_EQ(ASCIIToUTF16("23 hours"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, - delta_23h29m59s999ms_)); - EXPECT_EQ(ASCIIToUTF16("1 day"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_23h30m_)); - EXPECT_EQ(ASCIIToUTF16("1 day"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, - delta_1d11h59m59s999ms_)); - EXPECT_EQ(ASCIIToUTF16("2 days"), TimeFormat::Simple( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_SHORT, delta_1d12h_)); + EXPECT_EQ(u"0 secs", TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_0s_)); + EXPECT_EQ(u"0 secs", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_499ms_)); + EXPECT_EQ(u"1 sec", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_500ms_)); + EXPECT_EQ(u"1 sec", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1s499ms_)); + EXPECT_EQ(u"2 secs", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1s500ms_)); + EXPECT_EQ(u"59 secs", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_59s499ms_)); + EXPECT_EQ(u"1 min", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_59s500ms_)); + EXPECT_EQ(u"1 min", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1m29s999ms_)); + EXPECT_EQ(u"2 mins", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1m30s_)); + EXPECT_EQ(u"59 mins", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_59m29s999ms_)); + EXPECT_EQ(u"1 hour", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_59m30s_)); + EXPECT_EQ(u"1 hour", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1h29m59s999ms_)); + EXPECT_EQ(u"2 hours", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1h30m_)); + EXPECT_EQ(u"23 hours", TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, + delta_23h29m59s999ms_)); + EXPECT_EQ(u"1 day", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_23h30m_)); + EXPECT_EQ(u"1 day", TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, + delta_1d11h59m59s999ms_)); + EXPECT_EQ(u"2 days", + TimeFormat::Simple(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_SHORT, delta_1d12h_)); // Test rounding behavior (detailed). - EXPECT_EQ(ASCIIToUTF16("59 seconds"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 100, - delta_59s499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 minute and 0 seconds"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 2, - delta_59s500ms_)); - EXPECT_EQ(ASCIIToUTF16("1 minute"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 1, - delta_59s500ms_)); - EXPECT_EQ(ASCIIToUTF16("59 minutes and 59 seconds"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 60, - delta_59m59s499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 hour and 0 minutes"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 59, - delta_59m59s499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 hour and 0 minutes"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 2, - delta_59m59s499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 hour"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 1, - delta_59m59s499ms_)); - EXPECT_EQ(ASCIIToUTF16("1 hour"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 1, - delta_59m59s500ms_)); - EXPECT_EQ(ASCIIToUTF16("1 hour and 0 minutes"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 2, - delta_59m59s500ms_)); - EXPECT_EQ(ASCIIToUTF16("23 hours and 59 minutes"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 24, - delta_23h59m29s999ms_)); - EXPECT_EQ(ASCIIToUTF16("1 day and 0 hours"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 23, - delta_23h59m29s999ms_)); - EXPECT_EQ(ASCIIToUTF16("1 day and 0 hours"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 2, - delta_23h59m29s999ms_)); - EXPECT_EQ(ASCIIToUTF16("1 day"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 1, - delta_23h59m29s999ms_)); - EXPECT_EQ(ASCIIToUTF16("1 day"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 1, - delta_23h59m30s_)); - EXPECT_EQ(ASCIIToUTF16("1 day and 0 hours"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, 2, - delta_23h59m30s_)); - EXPECT_EQ(ASCIIToUTF16("1 day and 0 hours"), TimeFormat::Detailed( - TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, -1, - delta_23h59m30s_)); + EXPECT_EQ(u"59 seconds", TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 100, + delta_59s499ms_)); + EXPECT_EQ(u"1 minute and 0 seconds", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 2, delta_59s500ms_)); + EXPECT_EQ(u"1 minute", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 1, delta_59s500ms_)); + EXPECT_EQ( + u"59 minutes and 59 seconds", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 60, delta_59m59s499ms_)); + EXPECT_EQ( + u"1 hour and 0 minutes", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 59, delta_59m59s499ms_)); + EXPECT_EQ( + u"1 hour and 0 minutes", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 2, delta_59m59s499ms_)); + EXPECT_EQ(u"1 hour", TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 1, + delta_59m59s499ms_)); + EXPECT_EQ(u"1 hour", TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 1, + delta_59m59s500ms_)); + EXPECT_EQ( + u"1 hour and 0 minutes", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 2, delta_59m59s500ms_)); + EXPECT_EQ( + u"23 hours and 59 minutes", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 24, delta_23h59m29s999ms_)); + EXPECT_EQ( + u"1 day and 0 hours", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 23, delta_23h59m29s999ms_)); + EXPECT_EQ( + u"1 day and 0 hours", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + 2, delta_23h59m29s999ms_)); + EXPECT_EQ(u"1 day", TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 1, + delta_23h59m29s999ms_)); + EXPECT_EQ(u"1 day", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 1, delta_23h59m30s_)); + EXPECT_EQ(u"1 day and 0 hours", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, + TimeFormat::LENGTH_LONG, 2, delta_23h59m30s_)); + EXPECT_EQ( + u"1 day and 0 hours", + TimeFormat::Detailed(TimeFormat::FORMAT_DURATION, TimeFormat::LENGTH_LONG, + -1, delta_23h59m30s_)); } // Test strings in default code path. @@ -443,20 +495,20 @@ TEST_F(TimeFormatTest, SimpleAndDetailedStringFallback) { // crbug.com/159388: This test fails when daylight savings time ends. TEST_F(TimeFormatTest, RelativeDate) { base::Time now = base::Time::Now(); - base::string16 today_str = TimeFormat::RelativeDate(now, NULL); - EXPECT_EQ(ASCIIToUTF16("Today"), today_str); + std::u16string today_str = TimeFormat::RelativeDate(now, NULL); + EXPECT_EQ(u"Today", today_str); base::Time yesterday = now - TimeDelta::FromDays(1); - base::string16 yesterday_str = TimeFormat::RelativeDate(yesterday, NULL); - EXPECT_EQ(ASCIIToUTF16("Yesterday"), yesterday_str); + std::u16string yesterday_str = TimeFormat::RelativeDate(yesterday, NULL); + EXPECT_EQ(u"Yesterday", yesterday_str); base::Time two_days_ago = now - TimeDelta::FromDays(2); - base::string16 two_days_ago_str = + std::u16string two_days_ago_str = TimeFormat::RelativeDate(two_days_ago, NULL); EXPECT_TRUE(two_days_ago_str.empty()); base::Time a_week_ago = now - TimeDelta::FromDays(7); - base::string16 a_week_ago_str = TimeFormat::RelativeDate(a_week_ago, NULL); + std::u16string a_week_ago_str = TimeFormat::RelativeDate(a_week_ago, NULL); EXPECT_TRUE(a_week_ago_str.empty()); } diff --git a/chromium/ui/base/linux/OWNERS b/chromium/ui/base/linux/OWNERS new file mode 100644 index 00000000000..68d2959370f --- /dev/null +++ b/chromium/ui/base/linux/OWNERS @@ -0,0 +1 @@ +file://ui/base/x/OWNERS diff --git a/chromium/ui/base/linux/linux_desktop.cc b/chromium/ui/base/linux/linux_desktop.cc new file mode 100644 index 00000000000..b5e3c80e0fe --- /dev/null +++ b/chromium/ui/base/linux/linux_desktop.cc @@ -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. + +#include "ui/base/linux/linux_desktop.h" + +#include "base/environment.h" +#include "base/nix/xdg_util.h" +#include "base/strings/string_piece.h" +#include "base/values.h" + +namespace ui { + +namespace { + +// Must be in sync with the copy in //content/browser/gpu/gpu_internals_ui.cc. +base::Value NewDescriptionValuePair(base::StringPiece desc, + base::StringPiece value) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("description", base::Value(desc)); + dict.SetKey("value", base::Value(value)); + return dict; +} + +} // namespace + +base::Value GetDesktopEnvironmentInfoAsListValue() { + base::Value result(base::Value::Type::LIST); + auto env(base::Environment::Create()); + std::string value; + if (env->GetVar(base::nix::kXdgCurrentDesktopEnvVar, &value)) { + result.Append( + NewDescriptionValuePair(base::nix::kXdgCurrentDesktopEnvVar, value)); + } + if (env->GetVar(base::nix::kXdgSessionTypeEnvVar, &value)) { + result.Append( + NewDescriptionValuePair(base::nix::kXdgSessionTypeEnvVar, value)); + } + constexpr char kGDMSession[] = "GDMSESSION"; + if (env->GetVar(kGDMSession, &value)) + result.Append(NewDescriptionValuePair(kGDMSession, value)); + return result; +} + +} // namespace ui diff --git a/chromium/ui/base/linux/linux_desktop.h b/chromium/ui/base/linux/linux_desktop.h new file mode 100644 index 00000000000..15688cac26f --- /dev/null +++ b/chromium/ui/base/linux/linux_desktop.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_BASE_LINUX_LINUX_DESKTOP_H_ +#define UI_BASE_LINUX_LINUX_DESKTOP_H_ + +#include "base/component_export.h" + +namespace base { +class Value; +} // namespace base + +namespace ui { + +// Returns desktop environment info as list value. +COMPONENT_EXPORT(UI_BASE) base::Value GetDesktopEnvironmentInfoAsListValue(); + +} // namespace ui + +#endif // UI_BASE_LINUX_LINUX_DESKTOP_H_ diff --git a/chromium/ui/base/models/button_menu_item_model.cc b/chromium/ui/base/models/button_menu_item_model.cc index cfa584fa41e..6368f454a36 100644 --- a/chromium/ui/base/models/button_menu_item_model.cc +++ b/chromium/ui/base/models/button_menu_item_model.cc @@ -13,9 +13,9 @@ bool ButtonMenuItemModel::Delegate::IsItemForCommandIdDynamic( return false; } -base::string16 ButtonMenuItemModel::Delegate::GetLabelForCommandId( +std::u16string ButtonMenuItemModel::Delegate::GetLabelForCommandId( int command_id) const { - return base::string16(); + return std::u16string(); } bool ButtonMenuItemModel::Delegate::IsCommandIdEnabled(int command_id) const { @@ -36,7 +36,7 @@ bool ButtonMenuItemModel::Delegate::GetAcceleratorForCommandId( struct ButtonMenuItemModel::Item { int command_id; ButtonType type; - base::string16 label; + std::u16string label; bool part_of_group; }; @@ -58,7 +58,7 @@ void ButtonMenuItemModel::AddGroupItemWithStringId( } void ButtonMenuItemModel::AddImageItem(int command_id) { - Item item = {command_id, TYPE_BUTTON, base::string16(), false}; + Item item = {command_id, TYPE_BUTTON, std::u16string(), false}; items_.push_back(item); } @@ -69,7 +69,7 @@ void ButtonMenuItemModel::AddButtonLabel(int command_id, int string_id) { } void ButtonMenuItemModel::AddSpace() { - Item item = {0, TYPE_SPACE, base::string16(), false}; + Item item = {0, TYPE_SPACE, std::u16string(), false}; items_.push_back(item); } @@ -101,7 +101,7 @@ bool ButtonMenuItemModel::GetAcceleratorAt(int index, return false; } -base::string16 ButtonMenuItemModel::GetLabelAt(int index) const { +std::u16string ButtonMenuItemModel::GetLabelAt(int index) const { if (IsItemDynamicAt(index)) return delegate_->GetLabelForCommandId(GetCommandIdAt(index)); return items_[index].label; diff --git a/chromium/ui/base/models/button_menu_item_model.h b/chromium/ui/base/models/button_menu_item_model.h index 7772052fda8..f77bca4dc03 100644 --- a/chromium/ui/base/models/button_menu_item_model.h +++ b/chromium/ui/base/models/button_menu_item_model.h @@ -5,12 +5,12 @@ #ifndef UI_BASE_MODELS_BUTTON_MENU_ITEM_MODEL_H_ #define UI_BASE_MODELS_BUTTON_MENU_ITEM_MODEL_H_ +#include #include #include "base/compiler_specific.h" #include "base/component_export.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/base/accelerators/accelerator.h" namespace ui { @@ -30,7 +30,7 @@ class COMPONENT_EXPORT(UI_BASE) ButtonMenuItemModel { public: // Some command ids have labels that change over time. virtual bool IsItemForCommandIdDynamic(int command_id) const; - virtual base::string16 GetLabelForCommandId(int command_id) const; + virtual std::u16string GetLabelForCommandId(int command_id) const; // Performs the action associated with the specified command id. virtual void ExecuteCommand(int command_id, int event_flags) = 0; @@ -85,7 +85,7 @@ class COMPONENT_EXPORT(UI_BASE) ButtonMenuItemModel { bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const; // Returns the current label value for the button at |index|. - base::string16 GetLabelAt(int index) const; + std::u16string GetLabelAt(int index) const; // If the button at |index| should have its size equalized along with all // other items that have their PartOfGroup bit set. @@ -106,11 +106,11 @@ class COMPONENT_EXPORT(UI_BASE) ButtonMenuItemModel { // Returns whether clicking on |command_id| dismisses the menu. bool DoesCommandIdDismissMenu(int command_id) const; - const base::string16& label() const { return item_label_; } + const std::u16string& label() const { return item_label_; } private: // The non-clickable label to the left of the buttons. - base::string16 item_label_; + std::u16string item_label_; struct Item; std::vector items_; diff --git a/chromium/ui/base/models/combobox_model.cc b/chromium/ui/base/models/combobox_model.cc index a6a311fc465..d307ee0ec59 100644 --- a/chromium/ui/base/models/combobox_model.cc +++ b/chromium/ui/base/models/combobox_model.cc @@ -8,12 +8,12 @@ namespace ui { -base::string16 ComboboxModel::GetDropDownTextAt(int index) const { +std::u16string ComboboxModel::GetDropDownTextAt(int index) const { return GetItemAt(index); } -base::string16 ComboboxModel::GetDropDownSecondaryTextAt(int index) const { - return base::string16(); +std::u16string ComboboxModel::GetDropDownSecondaryTextAt(int index) const { + return std::u16string(); } ImageModel ComboboxModel::GetIconAt(int index) const { diff --git a/chromium/ui/base/models/combobox_model.h b/chromium/ui/base/models/combobox_model.h index 994ac2bbef7..5264aaa5550 100644 --- a/chromium/ui/base/models/combobox_model.h +++ b/chromium/ui/base/models/combobox_model.h @@ -5,8 +5,9 @@ #ifndef UI_BASE_MODELS_COMBOBOX_MODEL_H_ #define UI_BASE_MODELS_COMBOBOX_MODEL_H_ +#include + #include "base/component_export.h" -#include "base/strings/string16.h" namespace ui { @@ -22,15 +23,15 @@ class COMPONENT_EXPORT(UI_BASE) ComboboxModel { virtual int GetItemCount() const = 0; // Returns the string at the specified index. - virtual base::string16 GetItemAt(int index) const = 0; + virtual std::u16string GetItemAt(int index) const = 0; // Returns the string to be shown in the dropdown for the item at |index|. By // default, it returns GetItemAt(index). - virtual base::string16 GetDropDownTextAt(int index) const; + virtual std::u16string GetDropDownTextAt(int index) const; // Returns the secondary string at the specified index. Secondary strings are // displayed in a second line inside every menu item. - virtual base::string16 GetDropDownSecondaryTextAt(int index) const; + virtual std::u16string GetDropDownSecondaryTextAt(int index) const; // Gets the icon for the item at the specified index. ImageModel is empty if // there is no icon. diff --git a/chromium/ui/base/models/dialog_model.cc b/chromium/ui/base/models/dialog_model.cc index ceccc112e59..762a1136b98 100644 --- a/chromium/ui/base/models/dialog_model.cc +++ b/chromium/ui/base/models/dialog_model.cc @@ -26,7 +26,7 @@ std::unique_ptr DialogModel::Builder::Build() { DialogModel::Builder& DialogModel::Builder::AddOkButton( base::OnceClosure callback, - base::string16 label, + std::u16string label, const DialogModelButton::Params& params) { DCHECK(!model_->accept_callback_); model_->accept_callback_ = std::move(callback); @@ -42,7 +42,7 @@ DialogModel::Builder& DialogModel::Builder::AddOkButton( DialogModel::Builder& DialogModel::Builder::AddCancelButton( base::OnceClosure callback, - base::string16 label, + std::u16string label, const DialogModelButton::Params& params) { DCHECK(!model_->cancel_callback_); model_->cancel_callback_ = std::move(callback); @@ -58,7 +58,7 @@ DialogModel::Builder& DialogModel::Builder::AddCancelButton( DialogModel::Builder& DialogModel::Builder::AddDialogExtraButton( base::RepeatingCallback callback, - base::string16 label, + std::u16string label, const DialogModelButton::Params& params) { model_->extra_button_.emplace(model_->GetPassKey(), model_.get(), std::move(callback), std::move(label), params); @@ -95,15 +95,15 @@ void DialogModel::AddCheckbox(int unique_id, label, params)); } -void DialogModel::AddCombobox(base::string16 label, +void DialogModel::AddCombobox(std::u16string label, std::unique_ptr combobox_model, const DialogModelCombobox::Params& params) { AddField(std::make_unique( GetPassKey(), this, std::move(label), std::move(combobox_model), params)); } -void DialogModel::AddTextfield(base::string16 label, - base::string16 text, +void DialogModel::AddTextfield(std::u16string label, + std::u16string text, const DialogModelTextfield::Params& params) { AddField(std::make_unique( GetPassKey(), this, std::move(label), std::move(text), params)); diff --git a/chromium/ui/base/models/dialog_model.h b/chromium/ui/base/models/dialog_model.h index f219925a6ce..59ae51833a4 100644 --- a/chromium/ui/base/models/dialog_model.h +++ b/chromium/ui/base/models/dialog_model.h @@ -6,11 +6,11 @@ #define UI_BASE_MODELS_DIALOG_MODEL_H_ #include +#include #include "base/callback.h" #include "base/component_export.h" #include "base/containers/flat_map.h" -#include "base/strings/string16.h" #include "base/types/pass_key.h" #include "ui/base/models/dialog_model_field.h" #include "ui/base/models/dialog_model_host.h" @@ -64,11 +64,11 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelDelegate { // // auto dialog_model = // ui::DialogModel::Builder(std::move(model_delegate)) -// .SetTitle(base::ASCIIToUTF16("Hello, world!")) +// .SetTitle(u"Hello, world!") // .AddOkButton(base::BindOnce(&Delegate::OnDialogAccepted, // base::Unretained(model_delegate_ptr))) // .AddTextfield( -// base::ASCIIToUTF16("Name"), base::string16(), +// u"Name", std::u16string(), // ui::DialogModelTextfield::Params().SetUniqueId(kNameTextfield)) // .Build(); // @@ -122,7 +122,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { return *this; } - Builder& SetTitle(base::string16 title) { + Builder& SetTitle(std::u16string title) { model_->title_ = std::move(title); return *this; } @@ -169,11 +169,11 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { // DialogModelHost implementation. Builder& AddOkButton( base::OnceClosure callback, - base::string16 label = base::string16(), + std::u16string label = std::u16string(), const DialogModelButton::Params& params = DialogModelButton::Params()); Builder& AddCancelButton( base::OnceClosure callback, - base::string16 label = base::string16(), + std::u16string label = std::u16string(), const DialogModelButton::Params& params = DialogModelButton::Params()); // Use of the extra button in new dialogs are discouraged. If this is deemed @@ -181,7 +181,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { // them. Builder& AddDialogExtraButton( base::RepeatingCallback callback, - base::string16 label, + std::u16string label, const DialogModelButton::Params& params = DialogModelButton::Params()); // Adds body text. See DialogModel::AddBodyText(). @@ -200,7 +200,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { } // Adds a combobox. See DialogModel::AddCombobox(). - Builder& AddCombobox(base::string16 label, + Builder& AddCombobox(std::u16string label, std::unique_ptr combobox_model, const DialogModelCombobox::Params& params = DialogModelCombobox::Params()) { @@ -209,8 +209,8 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { } // Adds a textfield. See DialogModel::AddTextfield(). - Builder& AddTextfield(base::string16 label, - base::string16 text, + Builder& AddTextfield(std::u16string label, + std::u16string text, const DialogModelTextfield::Params& params = DialogModelTextfield::Params()) { model_->AddTextfield(std::move(label), std::move(text), params); @@ -247,14 +247,14 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { DialogModelCheckbox::Params()); // Adds a labeled combobox (label: [model]) at the end of the dialog model. - void AddCombobox(base::string16 label, + void AddCombobox(std::u16string label, std::unique_ptr combobox_model, const DialogModelCombobox::Params& params = DialogModelCombobox::Params()); // Adds a labeled textfield (label: [text]) at the end of the dialog model. - void AddTextfield(base::string16 label, - base::string16 text, + void AddTextfield(std::u16string label, + std::u16string text, const DialogModelTextfield::Params& params = DialogModelTextfield::Params()); @@ -289,7 +289,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { return override_show_close_button_; } - const base::string16& title(base::PassKey) const { + const std::u16string& title(base::PassKey) const { return title_; } @@ -340,7 +340,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModel final { base::Optional override_show_close_button_; bool close_on_deactivate_ = true; - base::string16 title_; + std::u16string title_; ImageModel icon_; std::vector> fields_; diff --git a/chromium/ui/base/models/dialog_model_field.cc b/chromium/ui/base/models/dialog_model_field.cc index a323903381f..9f017847913 100644 --- a/chromium/ui/base/models/dialog_model_field.cc +++ b/chromium/ui/base/models/dialog_model_field.cc @@ -29,10 +29,10 @@ DialogModelLabel::DialogModelLabel(int message_id, std::vector links) // labels with links. } -DialogModelLabel::DialogModelLabel(base::string16 fixed_string) +DialogModelLabel::DialogModelLabel(std::u16string fixed_string) : message_id_(-1), string_(std::move(fixed_string)) {} -const base::string16& DialogModelLabel::GetString( +const std::u16string& DialogModelLabel::GetString( base::PassKey) const { DCHECK(links_.empty()); return string_; @@ -134,7 +134,7 @@ DialogModelButton::DialogModelButton( base::PassKey pass_key, DialogModel* model, base::RepeatingCallback callback, - base::string16 label, + std::u16string label, const DialogModelButton::Params& params) : DialogModelField(pass_key, model, @@ -211,7 +211,7 @@ DialogModelCombobox::Params& DialogModelCombobox::Params::AddAccelerator( DialogModelCombobox::DialogModelCombobox( base::PassKey pass_key, DialogModel* model, - base::string16 label, + std::u16string label, std::unique_ptr combobox_model, const DialogModelCombobox::Params& params) : DialogModelField(pass_key, @@ -256,8 +256,8 @@ DialogModelTextfield::Params& DialogModelTextfield::Params::AddAccelerator( DialogModelTextfield::DialogModelTextfield( base::PassKey pass_key, DialogModel* model, - base::string16 label, - base::string16 text, + std::u16string label, + std::u16string text, const ui::DialogModelTextfield::Params& params) : DialogModelField(pass_key, model, @@ -271,7 +271,7 @@ DialogModelTextfield::DialogModelTextfield( DialogModelTextfield::~DialogModelTextfield() = default; void DialogModelTextfield::OnTextChanged(base::PassKey, - base::string16 text) { + std::u16string text) { text_ = std::move(text); } diff --git a/chromium/ui/base/models/dialog_model_field.h b/chromium/ui/base/models/dialog_model_field.h index 54b50c7670f..3815767d115 100644 --- a/chromium/ui/base/models/dialog_model_field.h +++ b/chromium/ui/base/models/dialog_model_field.h @@ -5,10 +5,11 @@ #ifndef UI_BASE_MODELS_DIALOG_MODEL_FIELD_H_ #define UI_BASE_MODELS_DIALOG_MODEL_FIELD_H_ +#include + #include "base/callback.h" #include "base/containers/flat_set.h" #include "base/gtest_prod_util.h" -#include "base/strings/string16.h" #include "base/types/pass_key.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/models/combobox_model.h" @@ -46,7 +47,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelLabel { }; explicit DialogModelLabel(int message_id); - explicit DialogModelLabel(base::string16 fixed_string); + explicit DialogModelLabel(std::u16string fixed_string); DialogModelLabel(const DialogModelLabel&); DialogModelLabel& operator=(const DialogModelLabel&) = delete; ~DialogModelLabel(); @@ -60,7 +61,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelLabel { // links() and message_id() to construct the final label. This is required to // style the final label appropriately and support link callbacks. The caller // is responsible for checking links().empty() before calling this. - const base::string16& GetString(base::PassKey) const; + const std::u16string& GetString(base::PassKey) const; DialogModelLabel& set_is_secondary() { is_secondary_ = true; @@ -87,7 +88,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelLabel { explicit DialogModelLabel(int message_id, std::vector links); const int message_id_; - const base::string16 string_; + const std::u16string string_; const std::vector links_; bool is_secondary_ = false; bool allow_character_break_ = false; @@ -175,7 +176,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelButton : public DialogModelField { DialogModelButton(base::PassKey pass_key, DialogModel* model, base::RepeatingCallback callback, - base::string16 label, + std::u16string label, const Params& params); DialogModelButton(const DialogModelButton&) = delete; DialogModelButton& operator=(const DialogModelButton&) = delete; @@ -183,7 +184,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelButton : public DialogModelField { // Methods with base::PassKey are only intended to be called // by the DialogModelHost implementation. - const base::string16& label(base::PassKey) const { + const std::u16string& label(base::PassKey) const { return label_; } void OnPressed(base::PassKey, const Event& event); @@ -191,7 +192,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelButton : public DialogModelField { private: friend class DialogModel; - const base::string16 label_; + const std::u16string label_; // The button callback gets called when the button is activated. Whether // that happens on key-press, release, etc. is implementation (and platform) // dependent. @@ -280,7 +281,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField { Params& AddAccelerator(Accelerator accelerator); - Params& SetAccessibleName(base::string16 accessible_name) { + Params& SetAccessibleName(std::u16string accessible_name) { accessible_name_ = std::move(accessible_name); return *this; } @@ -296,7 +297,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField { friend class DialogModelCombobox; int unique_id_ = -1; - base::string16 accessible_name_; + std::u16string accessible_name_; base::RepeatingClosure callback_; base::flat_set accelerators_; }; @@ -305,7 +306,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField { // fields. DialogModelCombobox(base::PassKey pass_key, DialogModel* model, - base::string16 label, + std::u16string label, std::unique_ptr combobox_model, const Params& params); DialogModelCombobox(const DialogModelCombobox&) = delete; @@ -317,10 +318,10 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField { // Methods with base::PassKey are only intended to be called // by the DialogModelHost implementation. - const base::string16& label(base::PassKey) const { + const std::u16string& label(base::PassKey) const { return label_; } - const base::string16& accessible_name(base::PassKey) const { + const std::u16string& accessible_name(base::PassKey) const { return accessible_name_; } void OnSelectedIndexChanged(base::PassKey, @@ -330,8 +331,8 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelCombobox : public DialogModelField { private: friend class DialogModel; - const base::string16 label_; - const base::string16 accessible_name_; + const std::u16string label_; + const std::u16string accessible_name_; int selected_index_; std::unique_ptr combobox_model_; base::RepeatingClosure callback_; @@ -355,7 +356,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelTextfield : public DialogModelField { Params& AddAccelerator(Accelerator accelerator); - Params& SetAccessibleName(base::string16 accessible_name) { + Params& SetAccessibleName(std::u16string accessible_name) { accessible_name_ = std::move(accessible_name); return *this; } @@ -364,7 +365,7 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelTextfield : public DialogModelField { friend class DialogModelTextfield; int unique_id_ = -1; - base::string16 accessible_name_; + std::u16string accessible_name_; base::flat_set accelerators_; }; @@ -372,31 +373,31 @@ class COMPONENT_EXPORT(UI_BASE) DialogModelTextfield : public DialogModelField { // fields. DialogModelTextfield(base::PassKey pass_key, DialogModel* model, - base::string16 label, - base::string16 text, + std::u16string label, + std::u16string text, const Params& params); DialogModelTextfield(const DialogModelTextfield&) = delete; DialogModelTextfield& operator=(const DialogModelTextfield&) = delete; ~DialogModelTextfield() override; - const base::string16& text() const { return text_; } + const std::u16string& text() const { return text_; } // Methods with base::PassKey are only intended to be called // by the DialogModelHost implementation. - const base::string16& label(base::PassKey) const { + const std::u16string& label(base::PassKey) const { return label_; } - const base::string16& accessible_name(base::PassKey) const { + const std::u16string& accessible_name(base::PassKey) const { return accessible_name_; } - void OnTextChanged(base::PassKey, base::string16 text); + void OnTextChanged(base::PassKey, std::u16string text); private: friend class DialogModel; - const base::string16 label_; - const base::string16 accessible_name_; - base::string16 text_; + const std::u16string label_; + const std::u16string accessible_name_; + std::u16string text_; }; } // namespace ui diff --git a/chromium/ui/base/models/dialog_model_unittest.cc b/chromium/ui/base/models/dialog_model_unittest.cc index 83b8a0e9ff0..4db911fc017 100644 --- a/chromium/ui/base/models/dialog_model_unittest.cc +++ b/chromium/ui/base/models/dialog_model_unittest.cc @@ -21,7 +21,7 @@ TEST_F(DialogModelButtonTest, UsesParamsUniqueId) { // are supported. std::unique_ptr model = DialogModel::Builder() - .AddOkButton(base::OnceClosure(), base::string16(), + .AddOkButton(base::OnceClosure(), std::u16string(), DialogModelButton::Params().SetUniqueId(kUniqueId)) .Build(); EXPECT_EQ(kUniqueId, @@ -36,7 +36,7 @@ TEST_F(DialogModelButtonTest, UsesParamsAccelerators) { // are supported. std::unique_ptr model = DialogModel::Builder() - .AddOkButton(base::OnceClosure(), base::string16(), + .AddOkButton(base::OnceClosure(), std::u16string(), DialogModelButton::Params() .AddAccelerator(accelerator_1) .AddAccelerator(accelerator_2)) @@ -58,7 +58,7 @@ TEST_F(DialogModelButtonTest, UsesCallback) { ++callback_count; last_event = std::make_unique(*event.AsKeyEvent()); }), - base::string16()) + std::u16string()) .Build(); DialogModelButton* const button = model->extra_button(TestDialogModelHost::GetPassKey()); @@ -92,7 +92,7 @@ class DialogModelDialogButtonTest : public testing::Test { &callback_called); // Label to verify the second parameter. - base::string16 label = base::ASCIIToUTF16("my cool button"); + std::u16string label = u"my cool button"; // The presence of an accelerator in |params| will be used to verify that // |params| are forwarded correctly to the DialogModelButton constructor. diff --git a/chromium/ui/base/models/menu_model.cc b/chromium/ui/base/models/menu_model.cc index d73c88e4152..d0eb4390321 100644 --- a/chromium/ui/base/models/menu_model.cc +++ b/chromium/ui/base/models/menu_model.cc @@ -56,12 +56,12 @@ bool MenuModel::GetModelAndIndexForCommandId(int command_id, return false; } -base::string16 MenuModel::GetMinorTextAt(int index) const { - return base::string16(); +std::u16string MenuModel::GetMinorTextAt(int index) const { + return std::u16string(); } -base::string16 MenuModel::GetSecondaryLabelAt(int index) const { - return base::string16(); +std::u16string MenuModel::GetSecondaryLabelAt(int index) const { + return std::u16string(); } ImageModel MenuModel::GetMinorIconAt(int index) const { diff --git a/chromium/ui/base/models/menu_model.h b/chromium/ui/base/models/menu_model.h index bf7988cab13..2f8dd2c08a9 100644 --- a/chromium/ui/base/models/menu_model.h +++ b/chromium/ui/base/models/menu_model.h @@ -5,9 +5,10 @@ #ifndef UI_BASE_MODELS_MENU_MODEL_H_ #define UI_BASE_MODELS_MENU_MODEL_H_ +#include + #include "base/component_export.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" #include "ui/base/models/menu_model_delegate.h" #include "ui/base/models/menu_separator_types.h" #include "ui/gfx/native_widget_types.h" @@ -64,15 +65,15 @@ class COMPONENT_EXPORT(UI_BASE) MenuModel virtual int GetCommandIdAt(int index) const = 0; // Returns the label of the item at the specified index. - virtual base::string16 GetLabelAt(int index) const = 0; + virtual std::u16string GetLabelAt(int index) const = 0; // Returns the secondary label of the item at the specified index. Secondary // label is shown below the label. - virtual base::string16 GetSecondaryLabelAt(int index) const; + virtual std::u16string GetSecondaryLabelAt(int index) const; // Returns the minor text of the item at the specified index. The minor text // is rendered to the right of the label and using the font GetLabelFontAt(). - virtual base::string16 GetMinorTextAt(int index) const; + virtual std::u16string GetMinorTextAt(int index) const; // Returns the minor icon of the item at the specified index. The minor icon // is rendered to the left of the minor text. diff --git a/chromium/ui/base/models/simple_combobox_model.cc b/chromium/ui/base/models/simple_combobox_model.cc index 64e05588544..42895146ee9 100644 --- a/chromium/ui/base/models/simple_combobox_model.cc +++ b/chromium/ui/base/models/simple_combobox_model.cc @@ -8,7 +8,7 @@ namespace ui { -SimpleComboboxModel::SimpleComboboxModel(std::vector items) +SimpleComboboxModel::SimpleComboboxModel(std::vector items) : items_(std::move(items)) {} SimpleComboboxModel::~SimpleComboboxModel() { @@ -18,7 +18,7 @@ int SimpleComboboxModel::GetItemCount() const { return items_.size(); } -base::string16 SimpleComboboxModel::GetItemAt(int index) const { +std::u16string SimpleComboboxModel::GetItemAt(int index) const { return items_[index]; } diff --git a/chromium/ui/base/models/simple_combobox_model.h b/chromium/ui/base/models/simple_combobox_model.h index 140760a604b..468fdc8e783 100644 --- a/chromium/ui/base/models/simple_combobox_model.h +++ b/chromium/ui/base/models/simple_combobox_model.h @@ -17,17 +17,17 @@ namespace ui { // An empty string will be a separator. class COMPONENT_EXPORT(UI_BASE) SimpleComboboxModel : public ComboboxModel { public: - explicit SimpleComboboxModel(std::vector items); + explicit SimpleComboboxModel(std::vector items); ~SimpleComboboxModel() override; // ui::ComboboxModel: int GetItemCount() const override; - base::string16 GetItemAt(int index) const override; + std::u16string GetItemAt(int index) const override; bool IsItemSeparatorAt(int index) const override; int GetDefaultIndex() const override; private: - const std::vector items_; + const std::vector items_; DISALLOW_COPY_AND_ASSIGN(SimpleComboboxModel); }; diff --git a/chromium/ui/base/models/simple_menu_model.cc b/chromium/ui/base/models/simple_menu_model.cc index 7db4ef95402..016dab77761 100644 --- a/chromium/ui/base/models/simple_menu_model.cc +++ b/chromium/ui/base/models/simple_menu_model.cc @@ -48,9 +48,9 @@ bool SimpleMenuModel::Delegate::IsItemForCommandIdDynamic( return false; } -base::string16 SimpleMenuModel::Delegate::GetLabelForCommandId( +std::u16string SimpleMenuModel::Delegate::GetLabelForCommandId( int command_id) const { - return base::string16(); + return std::u16string(); } ImageModel SimpleMenuModel::Delegate::GetIconForCommandId( @@ -77,7 +77,7 @@ SimpleMenuModel::SimpleMenuModel(Delegate* delegate) : delegate_(delegate) {} SimpleMenuModel::~SimpleMenuModel() { } -void SimpleMenuModel::AddItem(int command_id, const base::string16& label) { +void SimpleMenuModel::AddItem(int command_id, const std::u16string& label) { AppendItem(Item(command_id, TYPE_COMMAND, label)); } @@ -96,7 +96,7 @@ void SimpleMenuModel::AddItemWithStringId(int command_id, int string_id) { } void SimpleMenuModel::AddItemWithIcon(int command_id, - const base::string16& label, + const std::u16string& label, const ImageModel& icon) { Item item(command_id, TYPE_COMMAND, label); item.icon = icon; @@ -110,7 +110,7 @@ void SimpleMenuModel::AddItemWithStringIdAndIcon(int command_id, } void SimpleMenuModel::AddCheckItem(int command_id, - const base::string16& label) { + const std::u16string& label) { AppendItem(Item(command_id, TYPE_CHECK, label)); } @@ -119,7 +119,7 @@ void SimpleMenuModel::AddCheckItemWithStringId(int command_id, int string_id) { } void SimpleMenuModel::AddRadioItem(int command_id, - const base::string16& label, + const std::u16string& label, int group_id) { Item item(command_id, TYPE_RADIO, label); item.group_id = group_id; @@ -132,14 +132,14 @@ void SimpleMenuModel::AddRadioItemWithStringId(int command_id, int string_id, } void SimpleMenuModel::AddHighlightedItemWithIcon(int command_id, - const base::string16& label, + const std::u16string& label, const ImageModel& icon) { Item item(command_id, TYPE_HIGHLIGHTED, label); item.icon = icon; AppendItem(std::move(item)); } -void SimpleMenuModel::AddTitle(const base::string16& label) { +void SimpleMenuModel::AddTitle(const std::u16string& label) { // Title items are non-interactive and should not be enabled. Item title_item = Item(kTitleId, TYPE_TITLE, label); title_item.enabled = false; @@ -161,20 +161,20 @@ void SimpleMenuModel::AddSeparator(MenuSeparatorType separator_type) { if (separator_type == SPACING_SEPARATOR) NOTIMPLEMENTED(); #endif - Item item(kSeparatorId, TYPE_SEPARATOR, base::string16()); + Item item(kSeparatorId, TYPE_SEPARATOR, std::u16string()); item.separator_type = separator_type; AppendItem(std::move(item)); } void SimpleMenuModel::AddButtonItem(int command_id, ButtonMenuItemModel* model) { - Item item(command_id, TYPE_BUTTON_ITEM, base::string16()); + Item item(command_id, TYPE_BUTTON_ITEM, std::u16string()); item.button_model = model; AppendItem(std::move(item)); } void SimpleMenuModel::AddSubMenu(int command_id, - const base::string16& label, + const std::u16string& label, MenuModel* model) { Item item(command_id, TYPE_SUBMENU, label); item.submenu = model; @@ -197,7 +197,7 @@ void SimpleMenuModel::AddSubMenuWithStringIdAndIcon(int command_id, } void SimpleMenuModel::AddActionableSubMenu(int command_id, - const base::string16& label, + const std::u16string& label, MenuModel* model) { Item item(command_id, TYPE_ACTIONABLE_SUBMENU, label); item.submenu = model; @@ -218,7 +218,7 @@ void SimpleMenuModel::AddActionableSubmenuWithStringIdAndIcon( void SimpleMenuModel::InsertItemAt(int index, int command_id, - const base::string16& label) { + const std::u16string& label) { InsertItemAtIndex(Item(command_id, TYPE_COMMAND, label), index); } @@ -234,14 +234,14 @@ void SimpleMenuModel::InsertSeparatorAt(int index, NOTIMPLEMENTED(); } #endif - Item item(kSeparatorId, TYPE_SEPARATOR, base::string16()); + Item item(kSeparatorId, TYPE_SEPARATOR, std::u16string()); item.separator_type = separator_type; InsertItemAtIndex(std::move(item), index); } void SimpleMenuModel::InsertCheckItemAt(int index, int command_id, - const base::string16& label) { + const std::u16string& label) { InsertItemAtIndex(Item(command_id, TYPE_CHECK, label), index); } @@ -252,7 +252,7 @@ void SimpleMenuModel::InsertCheckItemWithStringIdAt( void SimpleMenuModel::InsertRadioItemAt(int index, int command_id, - const base::string16& label, + const std::u16string& label, int group_id) { Item item(command_id, TYPE_RADIO, label); item.group_id = group_id; @@ -267,7 +267,7 @@ void SimpleMenuModel::InsertRadioItemWithStringIdAt( void SimpleMenuModel::InsertSubMenuAt(int index, int command_id, - const base::string16& label, + const std::u16string& label, MenuModel* model) { Item item(command_id, TYPE_SUBMENU, label); item.submenu = model; @@ -290,13 +290,13 @@ void SimpleMenuModel::SetIcon(int index, const ui::ImageModel& icon) { MenuItemsChanged(); } -void SimpleMenuModel::SetLabel(int index, const base::string16& label) { +void SimpleMenuModel::SetLabel(int index, const std::u16string& label) { items_[ValidateItemIndex(index)].label = label; MenuItemsChanged(); } void SimpleMenuModel::SetMinorText(int index, - const base::string16& minor_text) { + const std::u16string& minor_text) { items_[ValidateItemIndex(index)].minor_text = minor_text; } @@ -371,13 +371,13 @@ int SimpleMenuModel::GetCommandIdAt(int index) const { return items_[ValidateItemIndex(index)].command_id; } -base::string16 SimpleMenuModel::GetLabelAt(int index) const { +std::u16string SimpleMenuModel::GetLabelAt(int index) const { if (IsItemDynamicAt(index)) return delegate_->GetLabelForCommandId(GetCommandIdAt(index)); return items_[ValidateItemIndex(index)].label; } -base::string16 SimpleMenuModel::GetMinorTextAt(int index) const { +std::u16string SimpleMenuModel::GetMinorTextAt(int index) const { return items_[ValidateItemIndex(index)].minor_text; } @@ -503,7 +503,7 @@ void SimpleMenuModel::MenuItemsChanged() { // SimpleMenuModel, Private: SimpleMenuModel::Item::Item(Item&&) = default; -SimpleMenuModel::Item::Item(int command_id, ItemType type, base::string16 label) +SimpleMenuModel::Item::Item(int command_id, ItemType type, std::u16string label) : command_id(command_id), type(type), label(label) {} SimpleMenuModel::Item& SimpleMenuModel::Item::operator=(Item&&) = default; SimpleMenuModel::Item::~Item() = default; diff --git a/chromium/ui/base/models/simple_menu_model.h b/chromium/ui/base/models/simple_menu_model.h index 7cefe1d152e..5ab6c93bb35 100644 --- a/chromium/ui/base/models/simple_menu_model.h +++ b/chromium/ui/base/models/simple_menu_model.h @@ -12,7 +12,6 @@ #include "base/component_export.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/models/image_model.h" #include "ui/base/models/menu_model.h" @@ -50,7 +49,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { // Some command ids have labels and icons that change over time. virtual bool IsItemForCommandIdDynamic(int command_id) const; - virtual base::string16 GetLabelForCommandId(int command_id) const; + virtual std::u16string GetLabelForCommandId(int command_id) const; // Gets the icon for the item with the specified id. virtual ImageModel GetIconForCommandId(int command_id) const; @@ -81,22 +80,22 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { ~SimpleMenuModel() override; // Methods for adding items to the model. - void AddItem(int command_id, const base::string16& label); + void AddItem(int command_id, const std::u16string& label); void AddItemWithStringId(int command_id, int string_id); void AddItemWithIcon(int command_id, - const base::string16& label, + const std::u16string& label, const ui::ImageModel& icon); void AddItemWithStringIdAndIcon(int command_id, int string_id, const ui::ImageModel& icon); - void AddCheckItem(int command_id, const base::string16& label); + void AddCheckItem(int command_id, const std::u16string& label); void AddCheckItemWithStringId(int command_id, int string_id); - void AddRadioItem(int command_id, const base::string16& label, int group_id); + void AddRadioItem(int command_id, const std::u16string& label, int group_id); void AddRadioItemWithStringId(int command_id, int string_id, int group_id); void AddHighlightedItemWithIcon(int command_id, - const base::string16& label, + const std::u16string& label, const ui::ImageModel& icon); - void AddTitle(const base::string16& label); + void AddTitle(const std::u16string& label); // Adds a separator of the specified type to the model. // - Adding a separator after another separator is always invalid if they @@ -109,7 +108,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { // owned by the same owner of this SimpleMenuModel. void AddButtonItem(int command_id, ButtonMenuItemModel* model); void AddSubMenu(int command_id, - const base::string16& label, + const std::u16string& label, MenuModel* model); void AddSubMenuWithStringId(int command_id, int string_id, MenuModel* model); void AddSubMenuWithStringIdAndIcon(int command_id, @@ -117,7 +116,7 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { MenuModel* model, const ui::ImageModel& icon); void AddActionableSubMenu(int command_id, - const base::string16& label, + const std::u16string& label, MenuModel* model); void AddActionableSubmenuWithStringIdAndIcon(int command_id, int string_id, @@ -125,22 +124,22 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { const ui::ImageModel& icon); // Methods for inserting items into the model. - void InsertItemAt(int index, int command_id, const base::string16& label); + void InsertItemAt(int index, int command_id, const std::u16string& label); void InsertItemWithStringIdAt(int index, int command_id, int string_id); void InsertSeparatorAt(int index, MenuSeparatorType separator_type); void InsertCheckItemAt(int index, int command_id, - const base::string16& label); + const std::u16string& label); void InsertCheckItemWithStringIdAt(int index, int command_id, int string_id); void InsertRadioItemAt(int index, int command_id, - const base::string16& label, + const std::u16string& label, int group_id); void InsertRadioItemWithStringIdAt( int index, int command_id, int string_id, int group_id); void InsertSubMenuAt(int index, int command_id, - const base::string16& label, + const std::u16string& label, MenuModel* model); void InsertSubMenuWithStringIdAt( int index, int command_id, int string_id, MenuModel* model); @@ -152,10 +151,10 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { void SetIcon(int index, const ui::ImageModel& icon); // Sets the label for the item at |index|. - void SetLabel(int index, const base::string16& label); + void SetLabel(int index, const std::u16string& label); // Sets the minor text for the item at |index|. - void SetMinorText(int index, const base::string16& minor_text); + void SetMinorText(int index, const std::u16string& minor_text); // Sets the minor icon for the item at |index|. void SetMinorIcon(int index, const ui::ImageModel& minor_icon); @@ -185,8 +184,8 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { ItemType GetTypeAt(int index) const override; ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override; int GetCommandIdAt(int index) const override; - base::string16 GetLabelAt(int index) const override; - base::string16 GetMinorTextAt(int index) const override; + std::u16string GetLabelAt(int index) const override; + std::u16string GetMinorTextAt(int index) const override; ImageModel GetMinorIconAt(int index) const override; bool IsItemDynamicAt(int index) const override; bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override; @@ -216,14 +215,14 @@ class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { private: struct Item { Item(Item&&); - Item(int command_id, ItemType type, base::string16 label); + Item(int command_id, ItemType type, std::u16string label); Item& operator=(Item&&); ~Item(); int command_id = 0; ItemType type = TYPE_COMMAND; - base::string16 label; - base::string16 minor_text; + std::u16string label; + std::u16string minor_text; ImageModel minor_icon; ImageModel icon; int group_id = -1; diff --git a/chromium/ui/base/models/simple_menu_model_unittest.cc b/chromium/ui/base/models/simple_menu_model_unittest.cc index b38debbc855..73d387086a6 100644 --- a/chromium/ui/base/models/simple_menu_model_unittest.cc +++ b/chromium/ui/base/models/simple_menu_model_unittest.cc @@ -63,20 +63,17 @@ class DelegateBase : public SimpleMenuModel::Delegate { TEST(SimpleMenuModelTest, SetLabel) { SimpleMenuModel simple_menu_model(nullptr); - simple_menu_model.AddItem(/*command_id*/ 5, - base::ASCIIToUTF16("menu item 0")); + simple_menu_model.AddItem(/*command_id*/ 5, u"menu item 0"); - simple_menu_model.SetLabel(/*index*/ 0, base::ASCIIToUTF16("new label")); + simple_menu_model.SetLabel(/*index*/ 0, u"new label"); - ASSERT_EQ(base::ASCIIToUTF16("new label"), simple_menu_model.GetLabelAt(0)); + ASSERT_EQ(u"new label", simple_menu_model.GetLabelAt(0)); } TEST(SimpleMenuModelTest, SetEnabledAt) { SimpleMenuModel simple_menu_model(nullptr); - simple_menu_model.AddItem(/*command_id*/ 5, - base::ASCIIToUTF16("menu item 0")); - simple_menu_model.AddItem(/*command_id*/ 6, - base::ASCIIToUTF16("menu item 1")); + 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.SetEnabledAt(/*index*/ 0, false); simple_menu_model.SetEnabledAt(/*index*/ 1, true); @@ -87,10 +84,8 @@ TEST(SimpleMenuModelTest, SetEnabledAt) { TEST(SimpleMenuModelTest, SetVisibleAt) { SimpleMenuModel simple_menu_model(nullptr); - simple_menu_model.AddItem(/*command_id*/ 5, - base::ASCIIToUTF16("menu item 0")); - simple_menu_model.AddItem(/*command_id*/ 6, - base::ASCIIToUTF16("menu item 1")); + 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.SetVisibleAt(/*index*/ 0, false); simple_menu_model.SetVisibleAt(/*index*/ 1, true); @@ -101,7 +96,7 @@ TEST(SimpleMenuModelTest, SetVisibleAt) { TEST(SimpleMenuModelTest, IsEnabledAtWithNoDelegate) { SimpleMenuModel simple_menu_model(nullptr); - simple_menu_model.AddItem(/*command_id*/ 5, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 5, u"menu item"); simple_menu_model.SetEnabledAt(/*index*/ 0, false); ASSERT_FALSE(simple_menu_model.IsEnabledAt(0)); @@ -111,7 +106,7 @@ TEST(SimpleMenuModelTest, IsEnabledAtWithDelegateAndCommandEnabled) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); // CommandId 5 is enabled. - simple_menu_model.AddItem(/*command_id*/ 5, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 5, u"menu item"); simple_menu_model.SetEnabledAt(/*index*/ 0, true); // Should return false since the command_id 5 is enabled. @@ -122,8 +117,7 @@ TEST(SimpleMenuModelTest, IsEnabledAtWithDelegateAndCommandNotEnabled) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); // CommandId 108 is disabled. - simple_menu_model.AddItem(/*command_id*/ 108, - base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 108, u"menu item"); simple_menu_model.SetEnabledAt(/*index*/ 0, true); // Should return false since the command_id 108 is disabled. @@ -134,7 +128,7 @@ TEST(SimpleMenuModelTest, IsVisibleAtWithDelegateAndCommandVisible) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); // CommandId 5 is visible. - simple_menu_model.AddItem(/*command_id*/ 5, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 5, u"menu item"); simple_menu_model.SetVisibleAt(/*index*/ 0, true); // Should return false since the command_id 5 is enabled. @@ -145,8 +139,7 @@ TEST(SimpleMenuModelTest, IsVisibleAtWithDelegateAndCommandNotVisible) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); // CommandId 108 is not visible. - simple_menu_model.AddItem(/*command_id*/ 108, - base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 108, u"menu item"); simple_menu_model.SetVisibleAt(/*index*/ 0, true); // Should return false since the command_id 108 is not visible. @@ -156,10 +149,8 @@ TEST(SimpleMenuModelTest, IsVisibleAtWithDelegateAndCommandNotVisible) { TEST(SimpleMenuModelTest, IsAlertedAtViaDelegate) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); - simple_menu_model.AddItem(kAlertedCommandId, - base::ASCIIToUTF16("alerted item")); - simple_menu_model.AddItem(kAlertedCommandId + 1, - base::ASCIIToUTF16("non-alerted item")); + simple_menu_model.AddItem(kAlertedCommandId, u"alerted item"); + simple_menu_model.AddItem(kAlertedCommandId + 1, u"non-alerted item"); EXPECT_TRUE(simple_menu_model.IsAlertedAt(0)); EXPECT_FALSE(simple_menu_model.IsAlertedAt(1)); @@ -167,10 +158,8 @@ TEST(SimpleMenuModelTest, IsAlertedAtViaDelegate) { TEST(SimpleMenuModelTest, SetIsNewFeatureAt) { SimpleMenuModel simple_menu_model(nullptr); - simple_menu_model.AddItem(/*command_id*/ 5, - base::ASCIIToUTF16("menu item 0")); - simple_menu_model.AddItem(/*command_id*/ 6, - base::ASCIIToUTF16("menu item 1")); + 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.SetIsNewFeatureAt(/*index*/ 0, false); simple_menu_model.SetIsNewFeatureAt(/*index*/ 1, true); @@ -182,10 +171,10 @@ TEST(SimpleMenuModelTest, SetIsNewFeatureAt) { TEST(SimpleMenuModelTest, HasIconsViaDelegate) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); - simple_menu_model.AddItem(/*command_id*/ 10, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 10, u"menu item"); EXPECT_FALSE(simple_menu_model.HasIcons()); - simple_menu_model.AddItem(/*command_id*/ 11, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 11, u"menu item"); delegate.set_icon_on_item(11); EXPECT_TRUE(simple_menu_model.HasIcons()); } @@ -193,11 +182,11 @@ TEST(SimpleMenuModelTest, HasIconsViaDelegate) { TEST(SimpleMenuModelTest, HasIconsViaAddItem) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); - simple_menu_model.AddItem(/*command_id*/ 10, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 10, u"menu item"); EXPECT_FALSE(simple_menu_model.HasIcons()); simple_menu_model.AddItemWithIcon( - /*command_id*/ 11, base::ASCIIToUTF16("menu item"), + /*command_id*/ 11, u"menu item", ui::ImageModel::FromImage(gfx::test::CreateImage(16, 16))); EXPECT_TRUE(simple_menu_model.HasIcons()); } @@ -205,7 +194,7 @@ TEST(SimpleMenuModelTest, HasIconsViaAddItem) { TEST(SimpleMenuModelTest, HasIconsViaVectorIcon) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); - simple_menu_model.AddItem(/*command_id*/ 10, base::ASCIIToUTF16("menu item")); + simple_menu_model.AddItem(/*command_id*/ 10, u"menu item"); EXPECT_FALSE(simple_menu_model.HasIcons()); gfx::PathElement path[] = {gfx::CommandType::CIRCLE, 24, 18, 5}; @@ -213,7 +202,7 @@ TEST(SimpleMenuModelTest, HasIconsViaVectorIcon) { gfx::VectorIcon circle_icon = {rep, 1, "circle"}; simple_menu_model.AddItemWithIcon( - /*command_id*/ 11, base::ASCIIToUTF16("menu item"), + /*command_id*/ 11, u"menu item", ui::ImageModel::FromVectorIcon(circle_icon)); EXPECT_TRUE(simple_menu_model.HasIcons()); } diff --git a/chromium/ui/base/models/table_model.cc b/chromium/ui/base/models/table_model.cc index 5275d7089e2..9ebae294f57 100644 --- a/chromium/ui/base/models/table_model.cc +++ b/chromium/ui/base/models/table_model.cc @@ -47,15 +47,15 @@ gfx::ImageSkia TableModel::GetIcon(int row) { return gfx::ImageSkia(); } -base::string16 TableModel::GetTooltip(int row) { - return base::string16(); +std::u16string TableModel::GetTooltip(int row) { + return std::u16string(); } int TableModel::CompareValues(int row1, int row2, int column_id) { DCHECK(row1 >= 0 && row1 < RowCount() && row2 >= 0 && row2 < RowCount()); - base::string16 value1 = GetText(row1, column_id); - base::string16 value2 = GetText(row2, column_id); + std::u16string value1 = GetText(row1, column_id); + std::u16string value2 = GetText(row2, column_id); icu::Collator* collator = GetCollator(); if (collator) diff --git a/chromium/ui/base/models/table_model.h b/chromium/ui/base/models/table_model.h index 6e098fbe8dc..c7313d48c4f 100644 --- a/chromium/ui/base/models/table_model.h +++ b/chromium/ui/base/models/table_model.h @@ -5,10 +5,10 @@ #ifndef UI_BASE_MODELS_TABLE_MODEL_H_ #define UI_BASE_MODELS_TABLE_MODEL_H_ +#include #include #include "base/component_export.h" -#include "base/strings/string16.h" #include "third_party/icu/source/i18n/unicode/coll.h" namespace gfx { @@ -29,7 +29,7 @@ class COMPONENT_EXPORT(UI_BASE) TableModel { virtual int RowCount() = 0; // Returns the value at a particular location in text. - virtual base::string16 GetText(int row, int column_id) = 0; + virtual std::u16string GetText(int row, int column_id) = 0; // Returns the small icon (|kIconSize| x |kIconSize|) that should be displayed // in the first column before the text. This is only used when the TableView @@ -40,7 +40,7 @@ class COMPONENT_EXPORT(UI_BASE) TableModel { // Returns the tooltip, if any, to show for a particular row. If there are // multiple columns in the row, this will only be shown when hovering over // column zero. - virtual base::string16 GetTooltip(int row); + virtual std::u16string GetTooltip(int row); // Sets the observer for the model. The TableView should NOT take ownership // of the observer. @@ -78,7 +78,7 @@ struct COMPONENT_EXPORT(UI_BASE) TableColumn { int id; // The title for the column. - base::string16 title; + std::u16string title; // Alignment for the content. Alignment alignment; diff --git a/chromium/ui/base/models/tree_model.cc b/chromium/ui/base/models/tree_model.cc index a787f8cb8c4..1111970bb08 100644 --- a/chromium/ui/base/models/tree_model.cc +++ b/chromium/ui/base/models/tree_model.cc @@ -8,8 +8,7 @@ namespace ui { -void TreeModel::SetTitle(TreeModelNode* node, - const base::string16& title) { +void TreeModel::SetTitle(TreeModelNode* node, const std::u16string& title) { NOTREACHED(); } diff --git a/chromium/ui/base/models/tree_model.h b/chromium/ui/base/models/tree_model.h index 20dc6cdef24..b09a2f2448a 100644 --- a/chromium/ui/base/models/tree_model.h +++ b/chromium/ui/base/models/tree_model.h @@ -5,10 +5,10 @@ #ifndef UI_BASE_MODELS_TREE_MODEL_H_ #define UI_BASE_MODELS_TREE_MODEL_H_ +#include #include #include "base/component_export.h" -#include "base/strings/string16.h" namespace gfx { class ImageSkia; @@ -27,7 +27,7 @@ class TreeModel; class TreeModelNode { public: // Returns the title for the node. - virtual const base::string16& GetTitle() const = 0; + virtual const std::u16string& GetTitle() const = 0; protected: virtual ~TreeModelNode() {} @@ -86,7 +86,7 @@ class COMPONENT_EXPORT(UI_BASE) TreeModel { // Sets the title of |node|. // This is only invoked if the node is editable and the user edits a node. - virtual void SetTitle(TreeModelNode* node, const base::string16& title); + virtual void SetTitle(TreeModelNode* node, const std::u16string& title); // Returns the set of icons for the nodes in the tree. You only need override // this if you don't want to use the default folder icons. diff --git a/chromium/ui/base/models/tree_node_model.h b/chromium/ui/base/models/tree_node_model.h index d21bf9a66d0..41be3614bb4 100644 --- a/chromium/ui/base/models/tree_node_model.h +++ b/chromium/ui/base/models/tree_node_model.h @@ -9,12 +9,12 @@ #include #include +#include #include #include "base/check_op.h" #include "base/macros.h" #include "base/observer_list.h" -#include "base/strings/string16.h" #include "ui/base/models/tree_model.h" namespace bookmarks { @@ -44,9 +44,9 @@ namespace ui { // std::unique_ptr> root = // std::make_unique>(); // root->Add( -// std::make_unique>(ASCIIToUTF16("child 1"), 0)); +// std::make_unique>(u"child 1", 0)); // root->Add( -// std::make_unique>(ASCIIToUTF16("child 2"), 1)); +// std::make_unique>(u"child 2", 1)); // TreeNodeModel> model(std::move(root)); // // Two variants of TreeNode are provided here: @@ -80,7 +80,7 @@ class TreeNode : public TreeModelNode { TreeNode() : parent_(nullptr) {} - explicit TreeNode(const base::string16& title) + explicit TreeNode(const std::u16string& title) : title_(title), parent_(nullptr) {} ~TreeNode() override {} @@ -143,10 +143,10 @@ class TreeNode : public TreeModelNode { } // Sets the title of the node. - virtual void SetTitle(const base::string16& title) { title_ = title; } + virtual void SetTitle(const std::u16string& title) { title_ = title; } // TreeModelNode: - const base::string16& GetTitle() const override { return title_; } + const std::u16string& GetTitle() const override { return title_; } // Returns true if this == ancestor, or one of this nodes parents is // ancestor. @@ -163,7 +163,7 @@ class TreeNode : public TreeModelNode { friend class bookmarks::BookmarkModel; // Title displayed in the tree. - base::string16 title_; + std::u16string title_; // This node's parent. NodeType* parent_; @@ -186,9 +186,9 @@ class TreeNodeWithValue : public TreeNode> { TreeNodeWithValue() {} explicit TreeNodeWithValue(const ValueType& value) - : ParentType(base::string16()), value(value) {} + : ParentType(std::u16string()), value(value) {} - TreeNodeWithValue(const base::string16& title, const ValueType& value) + TreeNodeWithValue(const std::u16string& title, const ValueType& value) : ParentType(title), value(value) {} ValueType value; @@ -306,8 +306,7 @@ class TreeNodeModel : public TreeModel { observer_list_.RemoveObserver(observer); } - void SetTitle(TreeModelNode* node, - const base::string16& title) override { + void SetTitle(TreeModelNode* node, const std::u16string& title) override { DCHECK(node); AsNode(node)->SetTitle(title); NotifyObserverTreeNodeChanged(node); diff --git a/chromium/ui/base/models/tree_node_model_unittest.cc b/chromium/ui/base/models/tree_node_model_unittest.cc index 2b9418cf95e..d603d6b59d4 100644 --- a/chromium/ui/base/models/tree_node_model_unittest.cc +++ b/chromium/ui/base/models/tree_node_model_unittest.cc @@ -5,10 +5,10 @@ #include "ui/base/models/tree_node_model.h" #include +#include #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" @@ -246,12 +246,11 @@ TEST_F(TreeNodeModelTest, GetTotalNodeCount) { // Makes sure that we are notified when the node is renamed, // also makes sure the node is properly renamed. TEST_F(TreeNodeModelTest, SetTitle) { - TreeNodeModel model( - std::make_unique(ASCIIToUTF16("root"), 0)); + TreeNodeModel model(std::make_unique(u"root", 0)); TestNode* root = model.GetRoot(); model.AddObserver(this); - const base::string16 title(ASCIIToUTF16("root2")); + const std::u16string title(u"root2"); model.SetTitle(root, title); EXPECT_EQ("added=0 removed=0 changed=1", GetObserverCountStateAndClear()); EXPECT_EQ(title, root->GetTitle()); diff --git a/chromium/ui/base/prediction/linear_resampling.cc b/chromium/ui/base/prediction/linear_resampling.cc index 92bd5f07b2d..2f0590de7b7 100644 --- a/chromium/ui/base/prediction/linear_resampling.cc +++ b/chromium/ui/base/prediction/linear_resampling.cc @@ -6,7 +6,7 @@ #include -#include +#include "base/feature_list.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_unittest.cc b/chromium/ui/base/prediction/prediction_metrics_handler_unittest.cc index fcfa9c052a7..8ed0f380ab2 100644 --- a/chromium/ui/base/prediction/prediction_metrics_handler_unittest.cc +++ b/chromium/ui/base/prediction/prediction_metrics_handler_unittest.cc @@ -4,6 +4,8 @@ #include "ui/base/prediction/prediction_metrics_handler.h" +#include + #include "base/test/metrics/histogram_tester.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -64,7 +66,7 @@ class PredictionMetricsHandlerTest : public testing::Test { } void Reset() { - histogram_tester_.reset(new base::HistogramTester()); + histogram_tester_ = std::make_unique(); metrics_handler_->Reset(); } diff --git a/chromium/ui/base/resource/mock_resource_bundle_delegate.h b/chromium/ui/base/resource/mock_resource_bundle_delegate.h index 54e75e18b4b..68b519c3a76 100644 --- a/chromium/ui/base/resource/mock_resource_bundle_delegate.h +++ b/chromium/ui/base/resource/mock_resource_bundle_delegate.h @@ -33,7 +33,7 @@ class MockResourceBundleDelegate : public ResourceBundle::Delegate { ScaleFactor scale_factor, base::StringPiece* value)); MOCK_CONST_METHOD2(GetLocalizedString, - bool(int message_id, base::string16* value)); + bool(int message_id, std::u16string* value)); }; } // namespace ui diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc index 910662d25a4..bb1381fd20f 100644 --- a/chromium/ui/base/resource/resource_bundle.cc +++ b/chromium/ui/base/resource/resource_bundle.cc @@ -463,7 +463,7 @@ void ResourceBundle::OverrideLocalePakForTest(const base::FilePath& pak_path) { void ResourceBundle::OverrideLocaleStringResource( int resource_id, - const base::string16& string) { + const std::u16string& string) { overridden_locale_strings_[resource_id] = string; } @@ -471,8 +471,8 @@ const base::FilePath& ResourceBundle::GetOverriddenPakPath() const { return overridden_pak_path_; } -base::string16 ResourceBundle::MaybeMangleLocalizedString( - const base::string16& str) const { +std::u16string ResourceBundle::MaybeMangleLocalizedString( + const std::u16string& str) const { if (!mangle_localized_strings_) return str; @@ -492,11 +492,11 @@ base::string16 ResourceBundle::MaybeMangleLocalizedString( // For a string S, produce [[ --- S --- ]], where the number of dashes is 1/4 // of the number of characters in S. This makes S something around 50-75% // longer, except for extremely short strings, which get > 100% longer. - base::string16 start_marker = base::UTF8ToUTF16("[["); - base::string16 end_marker = base::UTF8ToUTF16("]]"); - base::string16 dashes = base::string16(str.size() / 4, '-'); + std::u16string start_marker = u"[["; + std::u16string end_marker = u"]]"; + std::u16string dashes = std::u16string(str.size() / 4, '-'); return base::JoinString({start_marker, dashes, str, dashes, end_marker}, - base::UTF8ToUTF16(" ")); + u" "); } std::string ResourceBundle::ReloadLocaleResources( @@ -689,7 +689,7 @@ bool ResourceBundle::IsBrotli(int resource_id) const { return HasBrotliHeader(raw_data); } -base::string16 ResourceBundle::GetLocalizedString(int resource_id) { +std::u16string ResourceBundle::GetLocalizedString(int resource_id) { #if DCHECK_IS_ON() { base::AutoLock lock_scope(*locale_resources_data_lock_); @@ -1019,8 +1019,8 @@ gfx::Image& ResourceBundle::GetEmptyImage() { return empty_image_; } -base::string16 ResourceBundle::GetLocalizedStringImpl(int resource_id) const { - base::string16 string; +std::u16string ResourceBundle::GetLocalizedStringImpl(int resource_id) const { + std::u16string string; if (delegate_ && delegate_->GetLocalizedString(resource_id, &string)) return MaybeMangleLocalizedString(string); @@ -1037,7 +1037,7 @@ base::string16 ResourceBundle::GetLocalizedStringImpl(int resource_id) const { // string (better than crashing). if (!locale_resources_data_.get()) { LOG(WARNING) << "locale resources are not loaded"; - return base::string16(); + return std::u16string(); } base::StringPiece data; @@ -1060,7 +1060,7 @@ base::string16 ResourceBundle::GetLocalizedStringImpl(int resource_id) const { if (data.empty()) { LOG(WARNING) << "unable to find resource: " << resource_id; NOTREACHED(); - return base::string16(); + return std::u16string(); } #endif // !defined(OS_FUCHSIA) } @@ -1071,9 +1071,9 @@ base::string16 ResourceBundle::GetLocalizedStringImpl(int resource_id) const { << "requested localized string from binary pack file"; // Data pack encodes strings as either UTF8 or UTF16. - base::string16 msg; + std::u16string msg; if (encoding == ResourceHandle::UTF16) { - msg = base::string16(reinterpret_cast(data.data()), + msg = std::u16string(reinterpret_cast(data.data()), data.length() / 2); } else if (encoding == ResourceHandle::UTF8) { msg = base::UTF8ToUTF16(data); diff --git a/chromium/ui/base/resource/resource_bundle.h b/chromium/ui/base/resource/resource_bundle.h index 48c329f00c3..9487fbaa237 100644 --- a/chromium/ui/base/resource/resource_bundle.h +++ b/chromium/ui/base/resource/resource_bundle.h @@ -20,7 +20,6 @@ #include "base/macros.h" #include "base/optional.h" #include "base/sequence_checker.h" -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "ui/base/layout.h" #include "ui/gfx/font_list.h" @@ -145,7 +144,7 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle { // Retrieve a localized string. Return true if a string was provided or // false to attempt retrieval of the default string. virtual bool GetLocalizedString(int message_id, - base::string16* value) const = 0; + std::u16string* value) const = 0; protected: virtual ~Delegate() {} @@ -305,7 +304,7 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle { // Get a localized string given a message id. Returns an empty string if the // resource_id is not found. - base::string16 GetLocalizedString(int resource_id); + std::u16string GetLocalizedString(int resource_id); // Get a localized resource (for example, localized image logo) given a // resource id. @@ -338,7 +337,7 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle { // the variations service to experiment with different UI strings. This method // is not thread safe! void OverrideLocaleStringResource(int resource_id, - const base::string16& string); + const std::u16string& string); // Returns the full pathname of the locale file to load, which may be a // compressed locale file ending in .gz. Returns an empty path if |app_locale| @@ -386,7 +385,7 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle { class ResourceBundleImageSource; friend class ResourceBundleImageSource; - using IdToStringMap = std::unordered_map; + using IdToStringMap = std::unordered_map; // Ctor/dtor are private, since we're a singleton. explicit ResourceBundle(Delegate* delegate); @@ -478,14 +477,14 @@ class COMPONENT_EXPORT(UI_BASE) ResourceBundle { // If mangling of localized strings is enabled, mangles |str| to make it // longer and to add begin and end markers so that any truncation of it is // visible and returns the mangled string. If not, returns |str|. - base::string16 MaybeMangleLocalizedString(const base::string16& str) const; + std::u16string MaybeMangleLocalizedString(const std::u16string& str) const; // An internal implementation of |GetLocalizedString()| without setting the // flag of whether overriding locale strings is supported to false. We don't // update this flag only in |InitDefaultFontList()| which is called earlier // than the overriding. This is okay, because the font list doesn't need to be // overridden by variations. - base::string16 GetLocalizedStringImpl(int resource_id) const; + std::u16string GetLocalizedStringImpl(int resource_id) const; // This pointer is guaranteed to outlive the ResourceBundle instance and may // be null. diff --git a/chromium/ui/base/resource/resource_bundle_unittest.cc b/chromium/ui/base/resource/resource_bundle_unittest.cc index 255adcedf3f..3bc04888f49 100644 --- a/chromium/ui/base/resource/resource_bundle_unittest.cc +++ b/chromium/ui/base/resource/resource_bundle_unittest.cc @@ -297,25 +297,25 @@ TEST_F(ResourceBundleTest, DelegateGetLocalizedString) { MockResourceBundleDelegate delegate; ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); - base::string16 data = base::ASCIIToUTF16("My test data"); + std::u16string data = u"My test data"; int resource_id = 5; EXPECT_CALL(delegate, GetLocalizedString(resource_id, _)) .Times(1) .WillOnce(DoAll(SetArgPointee<1>(data), Return(true))); - base::string16 result = resource_bundle->GetLocalizedString(resource_id); + std::u16string result = resource_bundle->GetLocalizedString(resource_id); EXPECT_EQ(data, result); } TEST_F(ResourceBundleTest, OverrideStringResource) { ResourceBundle* resource_bundle = CreateResourceBundle(nullptr); - base::string16 data = base::ASCIIToUTF16("My test data"); + std::u16string data = u"My test data"; int resource_id = 5; - base::string16 result = resource_bundle->GetLocalizedString(resource_id); - EXPECT_EQ(base::string16(), result); + std::u16string result = resource_bundle->GetLocalizedString(resource_id); + EXPECT_EQ(std::u16string(), result); resource_bundle->OverrideLocaleStringResource(resource_id, data); @@ -327,7 +327,7 @@ TEST_F(ResourceBundleTest, OverrideStringResource) { TEST_F(ResourceBundleTest, CanOverrideStringResources) { ResourceBundle* resource_bundle = CreateResourceBundle(nullptr); - base::string16 data = base::ASCIIToUTF16("My test data"); + std::u16string data = u"My test data"; int resource_id = 5; EXPECT_TRUE( @@ -342,16 +342,16 @@ TEST_F(ResourceBundleTest, DelegateGetLocalizedStringWithOverride) { MockResourceBundleDelegate delegate; ResourceBundle* resource_bundle = CreateResourceBundle(&delegate); - base::string16 delegate_data = base::ASCIIToUTF16("My delegate data"); + std::u16string delegate_data = u"My delegate data"; int resource_id = 5; EXPECT_CALL(delegate, GetLocalizedString(resource_id, _)) .Times(1) .WillOnce(DoAll(SetArgPointee<1>(delegate_data), Return(true))); - base::string16 override_data = base::ASCIIToUTF16("My override data"); + std::u16string override_data = u"My override data"; - base::string16 result = resource_bundle->GetLocalizedString(resource_id); + std::u16string result = resource_bundle->GetLocalizedString(resource_id); EXPECT_EQ(delegate_data, result); } diff --git a/chromium/ui/base/text/bytes_formatting.cc b/chromium/ui/base/text/bytes_formatting.cc index 999e29ffe6b..69380ebe2cd 100644 --- a/chromium/ui/base/text/bytes_formatting.cc +++ b/chromium/ui/base/text/bytes_formatting.cc @@ -36,14 +36,14 @@ const int kSpeedStrings[] = { IDS_APP_PEBIBYTES_PER_SECOND }; -base::string16 FormatBytesInternal(int64_t bytes, +std::u16string FormatBytesInternal(int64_t bytes, DataUnits units, bool show_units, const int* const suffix) { DCHECK(units >= DATA_UNITS_BYTE && units <= DATA_UNITS_PEBIBYTE); if (bytes < 0) { NOTREACHED() << "Negative bytes value"; - return base::string16(); + return std::u16string(); } // Put the quantity in the right units. @@ -55,7 +55,7 @@ base::string16 FormatBytesInternal(int64_t bytes, if (bytes != 0 && units != DATA_UNITS_BYTE && unit_amount < 100) fractional_digits = 1; - base::string16 result = base::FormatDouble(unit_amount, fractional_digits); + std::u16string result = base::FormatDouble(unit_amount, fractional_digits); if (show_units) result = l10n_util::GetStringFUTF16(suffix[units], result); @@ -93,23 +93,23 @@ DataUnits GetByteDisplayUnits(int64_t bytes) { return DataUnits(unit_index); } -base::string16 FormatBytesWithUnits(int64_t bytes, +std::u16string FormatBytesWithUnits(int64_t bytes, DataUnits units, bool show_units) { return FormatBytesInternal(bytes, units, show_units, kByteStrings); } -base::string16 FormatSpeedWithUnits(int64_t bytes, +std::u16string FormatSpeedWithUnits(int64_t bytes, DataUnits units, bool show_units) { return FormatBytesInternal(bytes, units, show_units, kSpeedStrings); } -base::string16 FormatBytes(int64_t bytes) { +std::u16string FormatBytes(int64_t bytes) { return FormatBytesWithUnits(bytes, GetByteDisplayUnits(bytes), true); } -base::string16 FormatSpeed(int64_t bytes) { +std::u16string FormatSpeed(int64_t bytes) { return FormatSpeedWithUnits(bytes, GetByteDisplayUnits(bytes), true); } diff --git a/chromium/ui/base/text/bytes_formatting.h b/chromium/ui/base/text/bytes_formatting.h index 424d5297435..8da2768c348 100644 --- a/chromium/ui/base/text/bytes_formatting.h +++ b/chromium/ui/base/text/bytes_formatting.h @@ -7,8 +7,9 @@ #include +#include + #include "base/component_export.h" -#include "base/strings/string16.h" namespace ui { @@ -17,12 +18,12 @@ namespace ui { // Simple call to return a byte quantity as a string in human-readable format. // Ex: FormatBytes(512) => "512 B" // Ex: FormatBytes(101479) => "99.1 kB" -COMPONENT_EXPORT(UI_BASE) base::string16 FormatBytes(int64_t bytes); +COMPONENT_EXPORT(UI_BASE) std::u16string FormatBytes(int64_t bytes); // Simple call to return a speed as a string in human-readable format. // Ex: FormatSpeed(512) => "512 B/s" // Ex: FormatSpeed(101479) => "99.1 kB/s" -COMPONENT_EXPORT(UI_BASE) base::string16 FormatSpeed(int64_t bytes); +COMPONENT_EXPORT(UI_BASE) std::u16string FormatSpeed(int64_t bytes); // Less-Simple API ------------------------------------------------------------- @@ -45,14 +46,14 @@ COMPONENT_EXPORT(UI_BASE) DataUnits GetByteDisplayUnits(int64_t bytes); // Ex: FormatBytes(512, DATA_UNITS_KIBIBYTE, true) => "0.5 kB" // Ex: FormatBytes(10*1024, DATA_UNITS_MEBIBYTE, false) => "0.1" COMPONENT_EXPORT(UI_BASE) -base::string16 FormatBytesWithUnits(int64_t bytes, +std::u16string FormatBytesWithUnits(int64_t bytes, DataUnits units, bool show_units); // As above, but with "/s" units for speed values. // Ex: FormatSpeed(512, DATA_UNITS_KIBIBYTE, true) => "0.5 kB/s" // Ex: FormatSpeed(10*1024, DATA_UNITS_MEBIBYTE, false) => "0.1" -base::string16 FormatSpeedWithUnits(int64_t bytes, +std::u16string FormatSpeedWithUnits(int64_t bytes, DataUnits units, bool show_units); diff --git a/chromium/ui/base/ui_base_features.cc b/chromium/ui/base/ui_base_features.cc index 67570bdd33c..58662f2778b 100644 --- a/chromium/ui/base/ui_base_features.cc +++ b/chromium/ui/base/ui_base_features.cc @@ -24,12 +24,18 @@ namespace features { // If enabled, calculate native window occlusion - Windows-only. const base::Feature kCalculateNativeWinOcclusion{ "CalculateNativeWinOcclusion", base::FEATURE_ENABLED_BY_DEFAULT}; + +// If enabled, listen for screen power state change and factor into the native +// window occlusion detection - Windows-only. +const base::Feature kScreenPowerListenerForNativeWinOcclusion{ + "ScreenPowerListenerForNativeWinOcclusion", + base::FEATURE_ENABLED_BY_DEFAULT}; #endif // OW_WIN // Whether or not filenames are supported on the clipboard. // https://crbug.com/1175483 const base::Feature kClipboardFilenames{"ClipboardFilenames", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Whether or not to delegate color queries to the color provider. const base::Feature kColorProviderRedirection = { @@ -60,6 +66,20 @@ bool IsImprovedKeyboardShortcutsEnabled() { return base::FeatureList::IsEnabled(kImprovedKeyboardShortcuts); } +const base::Feature kDeprecateAltClick = {"DeprecateAltClick", + base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsDeprecateAltClickEnabled() { + return base::FeatureList::IsEnabled(kDeprecateAltClick); +} + +const base::Feature kShortcutCustomizationApp = { + "ShortcutCustomizationApp", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsShortcutCustomizationAppEnabled() { + return base::FeatureList::IsEnabled(kShortcutCustomizationApp); +} + #endif // BUILDFLAG(IS_CHROMEOS_ASH) // Update of the virtual keyboard settings UI as described in @@ -84,8 +104,8 @@ const base::Feature kSystemCaptionStyle{"SystemCaptionStyle", const base::Feature kSystemKeyboardLock{"SystemKeyboardLock", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kNotificationIndicator = { - "EnableNotificationIndicator", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNotificationIndicator = {"EnableNotificationIndicator", + base::FEATURE_ENABLED_BY_DEFAULT}; bool IsNotificationIndicatorEnabled() { return base::FeatureList::IsEnabled(kNotificationIndicator); @@ -184,11 +204,12 @@ bool IsForcedColorsEnabled() { return forced_colors_enabled; } -// Enables the eye-dropper in the refresh color-picker for Windows and Mac. -// This feature will be released for other platforms in later milestones. +// Enables the eye-dropper in the refresh color-picker for Windows, Mac +// and Linux. This feature will be released for other platforms in later +// milestones. const base::Feature kEyeDropper { "EyeDropper", -#if defined(OS_WIN) || defined(OS_MAC) +#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT @@ -200,18 +221,8 @@ bool IsEyeDropperEnabled() { base::FeatureList::IsEnabled(features::kEyeDropper); } -// Enable the CSSColorSchemeUARendering feature for Windows, ChromeOS, Linux, -// and Mac. This feature will be released for Android in later milestones. See -// crbug.com/1086530 for the Desktop launch bug. const base::Feature kCSSColorSchemeUARendering = { - "CSSColorSchemeUARendering", -#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_LINUX) || \ - defined(OS_APPLE) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -}; + "CSSColorSchemeUARendering", base::FEATURE_ENABLED_BY_DEFAULT}; bool IsCSSColorSchemeUARenderingEnabled() { static const bool css_color_scheme_ua_rendering_enabled = @@ -219,18 +230,8 @@ bool IsCSSColorSchemeUARenderingEnabled() { return css_color_scheme_ua_rendering_enabled; } -// Enable the FormControlsRefresh feature for Windows, ChromeOS, Linux, and Mac. -// This feature will be released for Android in later milestones. See -// crbug.com/1012106 for the Windows launch bug, and crbug.com/1012108 for the -// Mac launch bug. const base::Feature kFormControlsRefresh = {"FormControlsRefresh", -#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_LINUX) || \ - defined(OS_APPLE) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -}; + base::FEATURE_ENABLED_BY_DEFAULT}; bool IsFormControlsRefreshEnabled() { static const bool form_controls_refresh_enabled = diff --git a/chromium/ui/base/ui_base_features.h b/chromium/ui/base/ui_base_features.h index c764b047529..fbcac263e2c 100644 --- a/chromium/ui/base/ui_base_features.h +++ b/chromium/ui/base/ui_base_features.h @@ -57,6 +57,8 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kPointerEventsForTouch; COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kPrecisionTouchpadLogging; +COMPONENT_EXPORT(UI_BASE_FEATURES) +extern const base::Feature kScreenPowerListenerForNativeWinOcclusion; COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kTSFImeSupport; // Returns true if the system should use WM_POINTER events for touch events. @@ -115,6 +117,18 @@ extern const base::Feature kImprovedKeyboardShortcuts; COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsImprovedKeyboardShortcutsEnabled(); +COMPONENT_EXPORT(UI_BASE_FEATURES) +extern const base::Feature kDeprecateAltClick; + +COMPONENT_EXPORT(UI_BASE_FEATURES) +bool IsDeprecateAltClickEnabled(); + +COMPONENT_EXPORT(UI_BASE_FEATURES) +extern const base::Feature kShortcutCustomizationApp; + +COMPONENT_EXPORT(UI_BASE_FEATURES) +bool IsShortcutCustomizationAppEnabled(); + #endif // Indicates whether DrmOverlayManager should used the synchronous API to diff --git a/chromium/ui/base/webui/jstemplate_builder.cc b/chromium/ui/base/webui/jstemplate_builder.cc index 0506b643ea3..5122d831cb2 100644 --- a/chromium/ui/base/webui/jstemplate_builder.cc +++ b/chromium/ui/base/webui/jstemplate_builder.cc @@ -16,7 +16,6 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/base/template_expressions.h" #include "ui/resources/grit/webui_generated_resources.h" -#include "ui/resources/grit/webui_resources.h" namespace webui { @@ -59,7 +58,7 @@ void AppendJsTemplateSourceHtml(std::string* output) { // fetch and cache the pointer of the jstemplate resource source text. std::string jstemplate_src = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_WEBUI_JS_JSTEMPLATE_COMPILED_JS); + IDR_JSTEMPLATE_JSTEMPLATE_COMPILED_JS); if (jstemplate_src.empty()) { NOTREACHED() << "Unable to get jstemplate src"; diff --git a/chromium/ui/base/win/accessibility_misc_utils.cc b/chromium/ui/base/win/accessibility_misc_utils.cc index a5d3c7af4c7..ef465a198df 100644 --- a/chromium/ui/base/win/accessibility_misc_utils.cc +++ b/chromium/ui/base/win/accessibility_misc_utils.cc @@ -17,7 +17,7 @@ UIATextProvider::~UIATextProvider() { } // static -bool UIATextProvider::CreateTextProvider(const string16& value, +bool UIATextProvider::CreateTextProvider(const std::u16string& value, bool editable, IUnknown** provider) { // Make sure ATL is initialized in this module. diff --git a/chromium/ui/base/win/accessibility_misc_utils.h b/chromium/ui/base/win/accessibility_misc_utils.h index 98116875245..3fba82ba0ad 100644 --- a/chromium/ui/base/win/accessibility_misc_utils.h +++ b/chromium/ui/base/win/accessibility_misc_utils.h @@ -4,13 +4,14 @@ #ifndef UI_BASE_WIN_ACCESSIBILITY_MISC_UTILS_H_ #define UI_BASE_WIN_ACCESSIBILITY_MISC_UTILS_H_ +#include + #include "base/win/atl.h" // Must be before UIAutomationCore.h #include #include "base/compiler_specific.h" #include "base/component_export.h" -#include "base/strings/string16.h" namespace base { namespace win { @@ -30,7 +31,7 @@ class COMPONENT_EXPORT(UI_BASE) UIATextProvider // Creates an instance of the UIATextProvider class. // Returns true on success - static bool CreateTextProvider(const string16& value, + static bool CreateTextProvider(const std::u16string& value, bool editable, IUnknown** provider); @@ -38,7 +39,7 @@ class COMPONENT_EXPORT(UI_BASE) UIATextProvider editable_ = editable; } - void set_value(const string16& value) { value_ = value; } + void set_value(const std::u16string& value) { value_ = value; } // // ITextProvider methods. @@ -60,7 +61,7 @@ class COMPONENT_EXPORT(UI_BASE) UIATextProvider private: bool editable_; - string16 value_; + std::u16string value_; }; } // win diff --git a/chromium/ui/base/win/message_box_win.cc b/chromium/ui/base/win/message_box_win.cc index 8665536bf4c..3f7700047b4 100644 --- a/chromium/ui/base/win/message_box_win.cc +++ b/chromium/ui/base/win/message_box_win.cc @@ -4,8 +4,9 @@ #include "ui/base/win/message_box_win.h" +#include + #include "base/i18n/rtl.h" -#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -22,11 +23,11 @@ int MessageBox(HWND hwnd, if (base::i18n::IsRTL()) actual_flags |= MB_RIGHT | MB_RTLREADING; - base::string16 localized_text = base::WideToUTF16(text); + std::u16string localized_text = base::WideToUTF16(text); base::i18n::AdjustStringForLocaleDirection(&localized_text); const wchar_t* text_ptr = base::as_wcstr(localized_text); - base::string16 localized_caption = base::WideToUTF16(caption); + std::u16string localized_caption = base::WideToUTF16(caption); base::i18n::AdjustStringForLocaleDirection(&localized_caption); const wchar_t* caption_ptr = base::as_wcstr(localized_caption); diff --git a/chromium/ui/base/win/shell.h b/chromium/ui/base/win/shell.h index 7cd212c4de4..8ad3b71b2f4 100644 --- a/chromium/ui/base/win/shell.h +++ b/chromium/ui/base/win/shell.h @@ -7,8 +7,9 @@ #include +#include + #include "base/component_export.h" -#include "base/strings/string16.h" namespace base { class FilePath; diff --git a/chromium/ui/base/window_open_disposition.h b/chromium/ui/base/window_open_disposition.h index ef07e966a05..c36806383f3 100644 --- a/chromium/ui/base/window_open_disposition.h +++ b/chromium/ui/base/window_open_disposition.h @@ -7,9 +7,6 @@ #include "base/component_export.h" -// DEPRECATED: Instead of introducing new references to this enum, use -// the generated ui::mojom::WindowOpenDisposition in -// ui/base/mojom/window_open_disposition.mojom.h. enum class WindowOpenDisposition { UNKNOWN, CURRENT_TAB, diff --git a/chromium/ui/base/x/BUILD.gn b/chromium/ui/base/x/BUILD.gn index 12ee24dd707..dc005256ec0 100644 --- a/chromium/ui/base/x/BUILD.gn +++ b/chromium/ui/base/x/BUILD.gn @@ -12,8 +12,12 @@ component("x") { output_name = "ui_base_x" sources = [ + "selection_requestor.cc", + "selection_requestor.h", "selection_utils.cc", "selection_utils.h", + "x11_clipboard_helper.cc", + "x11_clipboard_helper.h", "x11_cursor.cc", "x11_cursor.h", "x11_cursor_factory.cc", @@ -26,6 +30,8 @@ component("x") { "x11_display_manager.h", "x11_display_util.cc", "x11_display_util.h", + "x11_global_shortcut_listener.cc", + "x11_global_shortcut_listener.h", "x11_idle_query.cc", "x11_idle_query.h", "x11_menu_list.cc", @@ -52,27 +58,15 @@ component("x") { "x11_util.h", "x11_whole_screen_move_loop.cc", "x11_whole_screen_move_loop.h", - "x11_window.cc", - "x11_window.h", "x11_workspace_handler.cc", "x11_workspace_handler.h", + "x11_xrandr_interval_only_vsync_provider.cc", + "x11_xrandr_interval_only_vsync_provider.h", ] - if (is_linux || is_chromeos) { - sources += [ - "selection_owner.cc", - "selection_owner.h", - "x11_drag_context.cc", - "x11_drag_context.h", - "x11_drag_drop_client.cc", - "x11_drag_drop_client.h", - "x11_os_exchange_data_provider.cc", - "x11_os_exchange_data_provider.h", - ] - } - defines = [ "IS_UI_BASE_X_IMPL" ] + public_deps = [] deps = [ "//base", "//base:i18n", @@ -81,8 +75,6 @@ component("x") { "//skia", "//ui/base:data_exchange", "//ui/base:features", - "//ui/base:hit_test", - "//ui/base:wm_role_names", "//ui/base/clipboard:clipboard_types", "//ui/base/clipboard:file_info", "//ui/base/cursor:cursor_base", @@ -99,6 +91,20 @@ component("x") { "//ui/gfx/x", "//ui/platform_window/common", ] + + if (is_linux || is_chromeos) { + sources += [ + "selection_owner.cc", + "selection_owner.h", + "x11_drag_context.cc", + "x11_drag_context.h", + "x11_drag_drop_client.cc", + "x11_drag_drop_client.h", + "x11_os_exchange_data_provider.cc", + "x11_os_exchange_data_provider.h", + ] + public_deps += [ "//ui/base/dragdrop:types" ] + } } source_set("gl") { @@ -140,14 +146,17 @@ source_set("test_support") { source_set("unittests") { testonly = true sources = [ + "selection_requestor_unittest.cc", "x11_cursor_factory_unittest.cc", "x11_cursor_loader_unittest.cc", ] deps = [ ":x", "//base", + "//base/test:test_support", "//skia", "//testing/gtest", "//ui/gfx/geometry", + "//ui/gfx/x", ] } diff --git a/chromium/ui/base/x/selection_requestor.cc b/chromium/ui/base/x/selection_requestor.cc index 6c466d7e8a3..2fd537c1821 100644 --- a/chromium/ui/base/x/selection_requestor.cc +++ b/chromium/ui/base/x/selection_requestor.cc @@ -10,8 +10,6 @@ #include "ui/base/x/selection_owner.h" #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_util.h" -#include "ui/events/platform/platform_event_source.h" -#include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/xproto.h" #include "ui/gfx/x/xproto_util.h" @@ -42,14 +40,8 @@ std::vector CombineData( } // namespace -SelectionRequestor::SelectionRequestor(x11::Window x_window, - x11::EventObserver* observer) - : x_window_(x_window), - x_property_(x11::Atom::None), - observer_(observer), - current_request_index_(0u) { - x_property_ = x11::GetAtom(kChromeSelection); -} +SelectionRequestor::SelectionRequestor(x11::Window x_window) + : x_window_(x_window), x_property_(x11::GetAtom(kChromeSelection)) {} SelectionRequestor::~SelectionRequestor() = default; @@ -207,9 +199,6 @@ void SelectionRequestor::CompleteRequest(size_t index, bool success) { ++current_request_index_; ConvertSelectionForCurrentRequest(); } - - if (request->quit_closure) - std::move(request->quit_closure).Run(); } void SelectionRequestor::ConvertSelectionForCurrentRequest() { diff --git a/chromium/ui/base/x/selection_requestor.h b/chromium/ui/base/x/selection_requestor.h index 7770071492d..cd7b2e41d64 100644 --- a/chromium/ui/base/x/selection_requestor.h +++ b/chromium/ui/base/x/selection_requestor.h @@ -5,21 +5,13 @@ #ifndef UI_BASE_X_SELECTION_REQUESTOR_H_ #define UI_BASE_X_SELECTION_REQUESTOR_H_ -#include - +#include #include -#include "base/callback.h" #include "base/component_export.h" -#include "base/macros.h" #include "base/memory/ref_counted_memory.h" #include "base/time/time.h" -#include "ui/events/platform_event.h" -#include "ui/gfx/x/event.h" - -namespace x11 { -class EventObserver; -} +#include "ui/gfx/x/connection.h" namespace ui { class SelectionData; @@ -31,9 +23,11 @@ class SelectionData; // drop. This class interprets messages from the stateful selection request // API. SelectionRequestor should only deal with the X11 details; it does not // implement per-component fast-paths. -class COMPONENT_EXPORT(UI_BASE) SelectionRequestor { +class COMPONENT_EXPORT(UI_BASE_X) SelectionRequestor { public: - SelectionRequestor(x11::Window xwindow, x11::EventObserver* observer); + explicit SelectionRequestor(x11::Window xwindow); + SelectionRequestor(const SelectionRequestor&) = delete; + SelectionRequestor& operator=(const SelectionRequestor&) = delete; ~SelectionRequestor(); // Does the work of requesting |target| from |selection|, spinning up the @@ -94,9 +88,6 @@ class COMPONENT_EXPORT(UI_BASE) SelectionRequestor { // The time when the request should be aborted. base::TimeTicks timeout; - // Called to terminate the nested run loop. - base::OnceClosure quit_closure; - // True if the request is complete. bool completed; }; @@ -119,18 +110,11 @@ class COMPONENT_EXPORT(UI_BASE) SelectionRequestor { Request* GetCurrentRequest(); // Our X11 state. - x11::Window x_window_; + const x11::Window x_window_; // The property on |x_window_| set by the selection owner with the value of // the selection. - x11::Atom x_property_; - - // Observer which handles SelectionNotify and SelectionRequest for - // |selection_name_|. PerformBlockingConvertSelection() calls the - // observer directly if PerformBlockingConvertSelection() is called after - // the PlatformEventSource is destroyed. - // Not owned. - x11::EventObserver* observer_; + const x11::Atom x_property_; // In progress requests. Requests are added to the list at the start of // PerformBlockingConvertSelection() and are removed and destroyed right @@ -140,9 +124,7 @@ class COMPONENT_EXPORT(UI_BASE) SelectionRequestor { // The index of the currently active request in |requests_|. The active // request is the request for which XConvertSelection() has been // called and for which we are waiting for a SelectionNotify response. - size_t current_request_index_; - - DISALLOW_COPY_AND_ASSIGN(SelectionRequestor); + size_t current_request_index_ = 0u; }; } // namespace ui diff --git a/chromium/ui/base/x/selection_requestor_unittest.cc b/chromium/ui/base/x/selection_requestor_unittest.cc index 77deaaa42e5..0bffa98afab 100644 --- a/chromium/ui/base/x/selection_requestor_unittest.cc +++ b/chromium/ui/base/x/selection_requestor_unittest.cc @@ -16,7 +16,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_util.h" -#include "ui/events/platform/platform_event_source.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/event.h" #include "ui/gfx/x/x11_atom_cache.h" @@ -53,15 +52,11 @@ class SelectionRequestorTest : public testing::Test { void SetUp() override { // Create a window for the selection requestor to use. x_window_ = x11::CreateDummyWindow(); - - event_source_ = PlatformEventSource::CreateDefault(); - CHECK(PlatformEventSource::GetInstance()); - requestor_ = std::make_unique(x_window_, nullptr); + requestor_ = std::make_unique(x_window_); } void TearDown() override { requestor_.reset(); - event_source_.reset(); connection_->DestroyWindow({x_window_}); } @@ -70,7 +65,6 @@ class SelectionRequestorTest : public testing::Test { // |requestor_|'s window. x11::Window x_window_ = x11::Window::None; - std::unique_ptr event_source_; std::unique_ptr requestor_; base::test::SingleThreadTaskEnvironment task_environment_{ diff --git a/chromium/ui/base/x/selection_utils.cc b/chromium/ui/base/x/selection_utils.cc index 155cfc703bd..c6799bf083b 100644 --- a/chromium/ui/base/x/selection_utils.cc +++ b/chromium/ui/base/x/selection_utils.cc @@ -10,6 +10,8 @@ #include "base/containers/contains.h" #include "base/i18n/icu_string_conversions.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_refptr.h" #include "base/notreached.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -51,7 +53,7 @@ void GetAtomIntersection(const std::vector& desired, } } -void AddString16ToVector(const base::string16& str, +void AddString16ToVector(const std::u16string& str, std::vector* bytes) { const unsigned char* front = reinterpret_cast(str.data()); @@ -81,19 +83,19 @@ std::string RefCountedMemoryToString( return std::string(reinterpret_cast(front), size); } -base::string16 RefCountedMemoryToString16( +std::u16string RefCountedMemoryToString16( const scoped_refptr& memory) { if (!memory.get()) { NOTREACHED(); - return base::string16(); + return std::u16string(); } size_t size = memory->size(); if (!size) - return base::string16(); + return std::u16string(); const unsigned char* front = memory->front(); - return base::string16(reinterpret_cast(front), size / 2); + return std::u16string(reinterpret_cast(front), size / 2); } /////////////////////////////////////////////////////////////////////////////// @@ -188,17 +190,17 @@ std::string SelectionData::GetText() const { } } -base::string16 SelectionData::GetHtml() const { - base::string16 markup; +std::u16string SelectionData::GetHtml() const { + std::u16string markup; if (type_ == x11::GetAtom(kMimeTypeHTML)) { const unsigned char* data = GetData(); size_t size = GetSize(); - // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is + // If the data starts with U+FEFF, i.e., Byte Order Mark, assume it is // UTF-16, otherwise assume UTF-8. - if (size >= 2 && reinterpret_cast(data)[0] == 0xFEFF) { - markup.assign(reinterpret_cast(data) + 1, + if (size >= 2 && reinterpret_cast(data)[0] == u'\uFEFF') { + markup.assign(reinterpret_cast(data) + 1, (size / 2) - 1); } else { base::UTF8ToUTF16(reinterpret_cast(data), size, &markup); @@ -219,8 +221,17 @@ void SelectionData::AssignTo(std::string* result) const { *result = RefCountedMemoryToString(memory_); } -void SelectionData::AssignTo(base::string16* result) const { +void SelectionData::AssignTo(std::u16string* result) const { *result = RefCountedMemoryToString16(memory_); } +scoped_refptr SelectionData::TakeBytes() { + if (!memory_.get()) + return nullptr; + + auto* memory = memory_.release(); + return base::MakeRefCounted(memory->data(), + memory->size()); +} + } // namespace ui diff --git a/chromium/ui/base/x/selection_utils.h b/chromium/ui/base/x/selection_utils.h index 2183832130b..d24bd907bf5 100644 --- a/chromium/ui/base/x/selection_utils.h +++ b/chromium/ui/base/x/selection_utils.h @@ -28,9 +28,9 @@ void GetAtomIntersection(const std::vector& desired, const std::vector& offered, std::vector* output); -// Takes the raw bytes of the base::string16 and copies them into |bytes|. +// Takes the raw bytes of the std::u16string and copies them into |bytes|. COMPONENT_EXPORT(UI_BASE_X) -void AddString16ToVector(const base::string16& str, +void AddString16ToVector(const std::u16string& str, std::vector* bytes); // Tokenizes and parses the Selection Data as if it is a URI List. @@ -42,7 +42,7 @@ std::string RefCountedMemoryToString( const scoped_refptr& memory); COMPONENT_EXPORT(UI_BASE_X) -base::string16 RefCountedMemoryToString16( +std::u16string RefCountedMemoryToString16( const scoped_refptr& memory); /////////////////////////////////////////////////////////////////////////////// @@ -106,11 +106,14 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionData { // If |type_| is the HTML type, returns the data as a string16. This detects // guesses the character encoding of the source. - base::string16 GetHtml() const; + std::u16string GetHtml() const; // Assigns the raw data to the string. void AssignTo(std::string* result) const; - void AssignTo(base::string16* result) const; + void AssignTo(std::u16string* result) const; + + // Transfers ownership of |memory_| to the caller. + scoped_refptr TakeBytes(); private: x11::Atom type_; diff --git a/chromium/ui/base/x/x11_clipboard_helper.cc b/chromium/ui/base/x/x11_clipboard_helper.cc new file mode 100644 index 00000000000..04ce85ab9e3 --- /dev/null +++ b/chromium/ui/base/x/x11_clipboard_helper.cc @@ -0,0 +1,413 @@ +// 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/x/x11_clipboard_helper.h" + +#include +#include + +#include "base/containers/contains.h" +#include "base/feature_list.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/singleton.h" +#include "base/metrics/histogram_macros.h" +#include "base/time/time.h" +#include "ui/base/clipboard/clipboard_buffer.h" +#include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/ui_base_features.h" +#include "ui/base/x/selection_owner.h" +#include "ui/base/x/selection_requestor.h" +#include "ui/base/x/selection_utils.h" +#include "ui/base/x/x11_util.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/event.h" +#include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/x11_window_event_manager.h" +#include "ui/gfx/x/xfixes.h" +#include "ui/gfx/x/xproto.h" +#include "ui/gfx/x/xproto_util.h" + +namespace ui { + +namespace { + +const char kClipboard[] = "CLIPBOARD"; +const char kClipboardManager[] = "CLIPBOARD_MANAGER"; + +// Uses the XFixes API to notify about selection changes. +class SelectionChangeObserver : public x11::EventObserver { + public: + using SelectionChangeCallback = XClipboardHelper::SelectionChangeCallback; + + SelectionChangeObserver(const SelectionChangeObserver&) = delete; + SelectionChangeObserver& operator=(const SelectionChangeObserver&) = delete; + + static SelectionChangeObserver* Get(); + + void set_callback(SelectionChangeCallback callback) { + callback_ = std::move(callback); + } + + private: + friend struct base::DefaultSingletonTraits; + + SelectionChangeObserver(); + ~SelectionChangeObserver() override = default; + + // x11::EventObserver: + void OnEvent(const x11::Event& xev) override; + + const x11::Atom clipboard_atom_{}; + SelectionChangeCallback callback_; +}; + +SelectionChangeObserver::SelectionChangeObserver() + : clipboard_atom_(x11::GetAtom(kClipboard)) { + auto* connection = x11::Connection::Get(); + auto& xfixes = connection->xfixes(); + // Let the server know the client version. No need to sync since we don't + // care what version is running on the server. + xfixes.QueryVersion({x11::XFixes::major_version, x11::XFixes::minor_version}); + if (!xfixes.present()) + return; + + auto mask = x11::XFixes::SelectionEventMask::SetSelectionOwner | + x11::XFixes::SelectionEventMask::SelectionWindowDestroy | + x11::XFixes::SelectionEventMask::SelectionClientClose; + xfixes.SelectSelectionInput({GetX11RootWindow(), clipboard_atom_, mask}); + // This seems to be semi-optional. For some reason, registering for any + // selection notify events seems to subscribe us to events for both the + // primary and the clipboard buffers. Register anyway just to be safe. + xfixes.SelectSelectionInput({GetX11RootWindow(), x11::Atom::PRIMARY, mask}); + + connection->AddEventObserver(this); +} + +SelectionChangeObserver* SelectionChangeObserver::Get() { + return base::Singleton::get(); +} + +void SelectionChangeObserver::OnEvent(const x11::Event& xev) { + if (auto* ev = xev.As()) { + DCHECK(ev->selection == x11::Atom::PRIMARY || + ev->selection == clipboard_atom_) + << "Unexpected selection atom: " + << static_cast(ev->selection); + + if (callback_) { + callback_.Run(ev->selection == x11::Atom::PRIMARY + ? ClipboardBuffer::kSelection + : ClipboardBuffer::kCopyPaste); + } + } +} + +x11::Window GetSelectionOwner(x11::Atom selection) { + auto response = x11::Connection::Get()->GetSelectionOwner({selection}).Sync(); + return response ? response->owner : x11::Window::None; +} + +} // namespace + +class XClipboardHelper::TargetList { + public: + explicit TargetList(const std::vector& target_list) + : target_list_(target_list) {} + TargetList(const TargetList&) = default; + TargetList& operator=(const TargetList&) = default; + ~TargetList() = default; + + const std::vector& target_list() const { return target_list_; } + + bool ContainsText() const { + for (const auto& atom : GetTextAtomsFrom()) { + if (ContainsAtom(atom)) + return true; + } + return false; + } + + bool ContainsFormat(const ClipboardFormatType& format_type) const { + x11::Atom atom = x11::GetAtom(format_type.GetName().c_str()); + return ContainsAtom(atom); + } + + bool ContainsAtom(x11::Atom atom) const { + return base::Contains(target_list_, atom); + } + + private: + std::vector target_list_; +}; + +XClipboardHelper::XClipboardHelper( + SelectionChangeCallback selection_change_callback) + : connection_(x11::Connection::Get()), + x_root_window_(ui::GetX11RootWindow()), + x_window_(x11::CreateDummyWindow("Chromium Clipboard Window")), + selection_requestor_(std::make_unique(x_window_)), + clipboard_owner_(connection_, x_window_, x11::GetAtom(kClipboard)), + primary_owner_(connection_, x_window_, x11::Atom::PRIMARY) { + DCHECK(selection_requestor_); + + x11::SetStringProperty(x_window_, x11::Atom::WM_NAME, x11::Atom::STRING, + "Chromium clipboard"); + x_window_events_ = std::make_unique( + x_window_, x11::EventMask::PropertyChange); + connection_->AddEventObserver(this); + + SelectionChangeObserver::Get()->set_callback( + std::move(selection_change_callback)); +} + +XClipboardHelper::~XClipboardHelper() { + connection_->RemoveEventObserver(this); + connection_->DestroyWindow({x_window_}); + SelectionChangeObserver::Get()->set_callback(SelectionChangeCallback()); +} + +void XClipboardHelper::CreateNewClipboardData() { + clipboard_data_ = SelectionFormatMap(); +} + +void XClipboardHelper::InsertMapping( + const std::string& key, + const scoped_refptr& memory) { + x11::Atom atom_key = x11::GetAtom(key.c_str()); + clipboard_data_.Insert(atom_key, memory); +} + +void XClipboardHelper::TakeOwnershipOfSelection(ClipboardBuffer buffer) { + if (buffer == ClipboardBuffer::kCopyPaste) + return clipboard_owner_.TakeOwnershipOfSelection(clipboard_data_); + else + return primary_owner_.TakeOwnershipOfSelection(clipboard_data_); +} + +SelectionData XClipboardHelper::Read(ClipboardBuffer buffer, + const std::vector& types) { + x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); + if (GetSelectionOwner(selection_name) == x_window_) { + // We can local fastpath instead of playing the nested run loop game + // with the X server. + const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); + + for (const auto& type : types) { + auto format_map_it = format_map.find(type); + if (format_map_it != format_map.end()) + return SelectionData(format_map_it->first, format_map_it->second); + } + } else { + auto targets = GetTargetList(buffer); + + x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); + std::vector intersection; + GetAtomIntersection(types, targets.target_list(), &intersection); + return selection_requestor_->RequestAndWaitForTypes(selection_name, + intersection); + } + return SelectionData(); +} + +std::vector XClipboardHelper::GetAvailableTypes( + ClipboardBuffer buffer) { + std::vector available_types; + auto target_list = GetTargetList(buffer); + + if (target_list.ContainsText()) + available_types.push_back(kMimeTypeText); + if (target_list.ContainsFormat(ClipboardFormatType::GetHtmlType())) + available_types.push_back(kMimeTypeHTML); + if (target_list.ContainsFormat(ClipboardFormatType::GetRtfType())) + available_types.push_back(kMimeTypeRTF); + if (target_list.ContainsFormat(ClipboardFormatType::GetBitmapType())) + available_types.push_back(kMimeTypePNG); + // Only support filenames if chrome://flags#clipboard-filenames is enabled. + if (target_list.ContainsFormat(ClipboardFormatType::GetFilenamesType()) && + base::FeatureList::IsEnabled(features::kClipboardFilenames)) { + available_types.push_back(kMimeTypeURIList); + } + if (target_list.ContainsFormat(ClipboardFormatType::GetWebCustomDataType())) + available_types.push_back(kMimeTypeWebCustomData); + + return available_types; +} + +std::vector XClipboardHelper::GetAvailableAtomNames( + ClipboardBuffer buffer) { + auto target_list = GetTargetList(buffer).target_list(); + if (target_list.empty()) + return {}; + + auto* connection = x11::Connection::Get(); + std::vector> futures; + for (x11::Atom target : target_list) + futures.push_back(connection->GetAtomName({target})); + + std::vector atom_names; + atom_names.reserve(target_list.size()); + for (auto& future : futures) { + if (auto response = future.Sync()) + atom_names.push_back(response->name); + else + atom_names.emplace_back(); + } + return atom_names; +} + +bool XClipboardHelper::IsFormatAvailable(ClipboardBuffer buffer, + const ClipboardFormatType& format) { + auto target_list = GetTargetList(buffer); + if (format == ClipboardFormatType::GetPlainTextType() || + format == ClipboardFormatType::GetUrlType()) { + return target_list.ContainsText(); + } + return target_list.ContainsFormat(format); +} + +bool XClipboardHelper::IsSelectionOwner(ClipboardBuffer buffer) const { + x11::Atom selection = LookupSelectionForClipboardBuffer(buffer); + return GetSelectionOwner(selection) == x_window_; +} + +std::vector XClipboardHelper::GetTextAtoms() const { + return GetTextAtomsFrom(); +} + +std::vector XClipboardHelper::GetAtomsForFormat( + const ClipboardFormatType& format) { + return {x11::GetAtom(format.GetName().c_str())}; +} + +void XClipboardHelper::Clear(ClipboardBuffer buffer) { + if (buffer == ClipboardBuffer::kCopyPaste) + clipboard_owner_.ClearSelectionOwner(); + else + primary_owner_.ClearSelectionOwner(); +} + +void XClipboardHelper::StoreCopyPasteDataAndWait() { + x11::Atom selection = GetCopyPasteSelection(); + if (GetSelectionOwner(selection) != x_window_) + return; + + x11::Atom clipboard_manager_atom = x11::GetAtom(kClipboardManager); + if (GetSelectionOwner(clipboard_manager_atom) == x11::Window::None) + return; + + const SelectionFormatMap& format_map = LookupStorageForAtom(selection); + if (format_map.size() == 0) + return; + std::vector targets = format_map.GetTypes(); + + base::TimeTicks start = base::TimeTicks::Now(); + selection_requestor_->PerformBlockingConvertSelectionWithParameter( + x11::GetAtom(kClipboardManager), x11::GetAtom(kSaveTargets), targets); + UMA_HISTOGRAM_TIMES("Clipboard.X11StoreCopyPasteDuration", + base::TimeTicks::Now() - start); +} + +XClipboardHelper::TargetList XClipboardHelper::GetTargetList( + ClipboardBuffer buffer) { + x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); + std::vector out; + if (GetSelectionOwner(selection_name) == x_window_) { + // We can local fastpath and return the list of local targets. + const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); + + for (const auto& format : format_map) + out.push_back(format.first); + } else { + std::vector data; + x11::Atom out_type = x11::Atom::None; + + if (selection_requestor_->PerformBlockingConvertSelection( + selection_name, x11::GetAtom(kTargets), &data, &out_type)) { + // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) + if (out_type == x11::Atom::ATOM || out_type == x11::GetAtom(kTargets)) { + const x11::Atom* atom_array = + reinterpret_cast(data.data()); + for (size_t i = 0; i < data.size() / sizeof(x11::Atom); ++i) + out.push_back(atom_array[i]); + } + } else { + // There was no target list. Most Java apps doesn't offer a TARGETS list, + // even though they AWT to. They will offer individual text types if you + // ask. If this is the case we attempt to make sense of the contents as + // text. This is pretty unfortunate since it means we have to actually + // copy the data to see if it is available, but at least this path + // shouldn't be hit for conforming programs. + std::vector types = GetTextAtoms(); + for (const auto& text_atom : types) { + x11::Atom type = x11::Atom::None; + if (selection_requestor_->PerformBlockingConvertSelection( + selection_name, text_atom, nullptr, &type) && + type == text_atom) { + out.push_back(text_atom); + } + } + } + } + + return XClipboardHelper::TargetList(out); +} + +void XClipboardHelper::OnEvent(const x11::Event& xev) { + if (auto* request = xev.As()) { + if (request->owner != x_window_) + return; + if (request->selection == x11::Atom::PRIMARY) { + primary_owner_.OnSelectionRequest(*request); + } else { + // We should not get requests for the CLIPBOARD_MANAGER selection + // because we never take ownership of it. + DCHECK_EQ(GetCopyPasteSelection(), request->selection); + clipboard_owner_.OnSelectionRequest(*request); + } + } else if (auto* notify = xev.As()) { + if (notify->requestor == x_window_) + selection_requestor_->OnSelectionNotify(*notify); + } else if (auto* clear = xev.As()) { + if (clear->owner != x_window_) + return; + if (clear->selection == x11::Atom::PRIMARY) { + primary_owner_.OnSelectionClear(*clear); + } else { + // We should not get requests for the CLIPBOARD_MANAGER selection + // because we never take ownership of it. + DCHECK_EQ(GetCopyPasteSelection(), clear->selection); + clipboard_owner_.OnSelectionClear(*clear); + } + } else if (auto* prop = xev.As()) { + if (primary_owner_.CanDispatchPropertyEvent(*prop)) + primary_owner_.OnPropertyEvent(*prop); + if (clipboard_owner_.CanDispatchPropertyEvent(*prop)) + clipboard_owner_.OnPropertyEvent(*prop); + if (selection_requestor_->CanDispatchPropertyEvent(*prop)) + selection_requestor_->OnPropertyEvent(*prop); + } +} + +x11::Atom XClipboardHelper::LookupSelectionForClipboardBuffer( + ClipboardBuffer buffer) const { + if (buffer == ClipboardBuffer::kCopyPaste) + return GetCopyPasteSelection(); + + return x11::Atom::PRIMARY; +} + +x11::Atom XClipboardHelper::GetCopyPasteSelection() const { + return x11::GetAtom(kClipboard); +} + +const SelectionFormatMap& XClipboardHelper::LookupStorageForAtom( + x11::Atom atom) { + if (atom == x11::Atom::PRIMARY) + return primary_owner_.selection_format_map(); + + DCHECK_EQ(GetCopyPasteSelection(), atom); + return clipboard_owner_.selection_format_map(); +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_clipboard_helper.h b/chromium/ui/base/x/x11_clipboard_helper.h new file mode 100644 index 00000000000..79ce9f4f47a --- /dev/null +++ b/chromium/ui/base/x/x11_clipboard_helper.h @@ -0,0 +1,136 @@ +// 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_CLIPBOARD_HELPER_H_ +#define UI_BASE_X_X11_CLIPBOARD_HELPER_H_ + +#include +#include +#include +#include + +#include "base/callback_forward.h" +#include "base/component_export.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_refptr.h" +#include "ui/base/clipboard/clipboard_buffer.h" +#include "ui/base/clipboard/clipboard_format_type.h" +#include "ui/base/x/selection_owner.h" +#include "ui/base/x/selection_utils.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/xproto.h" + +namespace ui { + +class SelectionRequestor; + +// Helper class that provides core X11 clipboard integration code. Shared by +// both legacy and Ozone X11 backends. +// +// TODO(crbug.com/789065): Merge into X11ClipboardOzone class once ozone +// migration is complete and legacy backend gets removed. +class COMPONENT_EXPORT(UI_BASE_X) XClipboardHelper : public x11::EventObserver { + public: + using SelectionChangeCallback = + base::RepeatingCallback; + + explicit XClipboardHelper(SelectionChangeCallback selection_change_callback); + XClipboardHelper(const XClipboardHelper&) = delete; + XClipboardHelper& operator=(const XClipboardHelper&) = delete; + ~XClipboardHelper() override; + + // As we need to collect all the data types before we tell X11 that we own a + // particular selection, we create a temporary clipboard mapping that + // InsertMapping writes to. Then we commit it in TakeOwnershipOfSelection, + // where we save it in one of the clipboard data slots. + void CreateNewClipboardData(); + + // Inserts a mapping into clipboard_data_. + void InsertMapping(const std::string& key, + const scoped_refptr& memory); + + // Moves the temporary |clipboard_data_| to the long term data storage for + // |buffer|. + void TakeOwnershipOfSelection(ClipboardBuffer buffer); + + // Returns the first of |types| offered by the current selection holder, or + // returns nullptr if none of those types are available. Blocks until the data + // is fetched from the X server, unless we are the selection owner. + SelectionData Read(ClipboardBuffer buffer, + const std::vector& types); + + // Retrieves the list of possible data types the current clipboard owner has, + // for a given |buffer|. Blocks until the data is fetched from the X server, + // unless we are the selection owner. + std::vector GetAvailableTypes(ClipboardBuffer buffer); + + // Retrieves the list of target atom names currently available for reading in + // the clipboard, for a given |buffer|. Blocks until the data is fetched from + // the X server. + std::vector GetAvailableAtomNames(ClipboardBuffer buffer); + + // Tells if |format| is currently available for reading in clipboard |buffer|. + // Blocks until the data is fetched from the X server. + bool IsFormatAvailable(ClipboardBuffer buffer, + const ClipboardFormatType& format); + + // Tells if we currently own the selection for a given clipboard |buffer|. + bool IsSelectionOwner(ClipboardBuffer buffer) const; + + // Returns a list of all text atoms that we handle. + std::vector GetTextAtoms() const; + + // Returns a vector with a |format| converted to an X11 atom. + std::vector GetAtomsForFormat(const ClipboardFormatType& format); + + // Clears a certain clipboard buffer, whether we own it or not. + void Clear(ClipboardBuffer buffer); + + // If we own the CLIPBOARD selection, requests the clipboard manager to take + // ownership of it. + void StoreCopyPasteDataAndWait(); + + private: + class TargetList; + + // x11::EventObserver: + void OnEvent(const x11::Event& xev) override; + + TargetList GetTargetList(ClipboardBuffer buffer); + + // Returns the X11 selection atom that we pass to various XSelection functions + // for the given buffer. + x11::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const; + + // Returns the X11 selection atom that we pass to various XSelection functions + // for ClipboardBuffer::kCopyPaste. + x11::Atom GetCopyPasteSelection() const; + + // Finds the SelectionFormatMap for the incoming selection atom. + const SelectionFormatMap& LookupStorageForAtom(x11::Atom atom); + + // Our X11 state. + x11::Connection* const connection_; + const x11::Window x_root_window_; + + // Input-only window used as a selection owner. + x11::Window x_window_; + + // Events selected on |x_window_|. + std::unique_ptr x_window_events_; + + // Object which requests and receives selection data. + const std::unique_ptr selection_requestor_; + + // Temporary target map that we write to during DispatchObects. + SelectionFormatMap clipboard_data_; + + // Objects which offer selection data to other windows. + SelectionOwner clipboard_owner_; + SelectionOwner primary_owner_; +}; + +} // namespace ui + +#endif // UI_BASE_X_X11_CLIPBOARD_HELPER_H_ diff --git a/chromium/ui/base/x/x11_cursor_factory.cc b/chromium/ui/base/x/x11_cursor_factory.cc index b7557703714..5a569835525 100644 --- a/chromium/ui/base/x/x11_cursor_factory.cc +++ b/chromium/ui/base/x/x11_cursor_factory.cc @@ -33,19 +33,10 @@ scoped_refptr CreateInvisibleCursor(XCursorLoader* cursor_loader) { } // namespace X11CursorFactory::X11CursorFactory() - : cursor_loader_(std::make_unique(x11::Connection::Get())), - invisible_cursor_(CreateInvisibleCursor(cursor_loader_.get())) {} + : cursor_loader_(std::make_unique(x11::Connection::Get())) {} X11CursorFactory::~X11CursorFactory() = default; -base::Optional X11CursorFactory::GetDefaultCursor( - mojom::CursorType type) { - auto cursor = GetDefaultCursorInternal(type); - if (!cursor) - return base::nullopt; - return ToPlatformCursor(cursor.get()); -} - PlatformCursor X11CursorFactory::CreateImageCursor(mojom::CursorType type, const SkBitmap& bitmap, const gfx::Point& hotspot) { @@ -53,13 +44,13 @@ PlatformCursor X11CursorFactory::CreateImageCursor(mojom::CursorType type, // 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 |invisible_cursor_| is owned by the caller, and will be + // 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 |invisible_cursor_| being freed out from - // under us. - invisible_cursor_->AddRef(); - return ToPlatformCursor(invisible_cursor_.get()); + // 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; } auto cursor = cursor_loader_->CreateCursor(bitmap, hotspot); @@ -71,11 +62,11 @@ PlatformCursor X11CursorFactory::CreateAnimatedCursor( mojom::CursorType type, const std::vector& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms) { + base::TimeDelta frame_delay) { std::vector images; images.reserve(bitmaps.size()); for (const auto& bitmap : bitmaps) - images.push_back(XCursorLoader::Image{bitmap, hotspot, frame_delay_ms}); + images.push_back(XCursorLoader::Image{bitmap, hotspot, frame_delay}); auto cursor = cursor_loader_->CreateCursor(images); cursor->AddRef(); return ToPlatformCursor(cursor.get()); @@ -104,19 +95,17 @@ void X11CursorFactory::OnCursorThemeSizeChanged(int cursor_theme_size) { ClearThemeCursors(); } -scoped_refptr X11CursorFactory::GetDefaultCursorInternal( - mojom::CursorType type) { - if (type == mojom::CursorType::kNone) - return invisible_cursor_; - +PlatformCursor X11CursorFactory::GetDefaultCursor(mojom::CursorType type) { if (!default_cursors_.count(type)) { // Try to load a predefined X11 cursor. default_cursors_[type] = - cursor_loader_->LoadCursor(CursorNamesFromType(type)); + type == mojom::CursorType::kNone + ? CreateInvisibleCursor(cursor_loader_.get()) + : cursor_loader_->LoadCursor(CursorNamesFromType(type)); } // Returns owned default cursor for this type. - return default_cursors_[type]; + return default_cursors_[type].get(); } void X11CursorFactory::ClearThemeCursors() { diff --git a/chromium/ui/base/x/x11_cursor_factory.h b/chromium/ui/base/x/x11_cursor_factory.h index 9a9ae76b190..44b6ffbd7ef 100644 --- a/chromium/ui/base/x/x11_cursor_factory.h +++ b/chromium/ui/base/x/x11_cursor_factory.h @@ -31,16 +31,15 @@ class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory X11CursorFactory& operator=(const X11CursorFactory&) = delete; ~X11CursorFactory() override; - // CursorFactoryOzone: - base::Optional GetDefaultCursor( - mojom::CursorType type) 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& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms) override; + base::TimeDelta frame_delay) override; void RefImageCursor(PlatformCursor cursor) override; void UnrefImageCursor(PlatformCursor cursor) override; void ObserveThemeChanges() override; @@ -54,13 +53,6 @@ class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory std::unique_ptr cursor_loader_; - // Loads/caches default cursor or returns cached version. - scoped_refptr GetDefaultCursorInternal(mojom::CursorType type); - - // Holds a single instance of the invisible cursor. X11 has no way to hide - // the cursor so an invisible cursor mimics that. - scoped_refptr invisible_cursor_; - std::map> default_cursors_; base::ScopedObservation diff --git a/chromium/ui/base/x/x11_cursor_factory_unittest.cc b/chromium/ui/base/x/x11_cursor_factory_unittest.cc index bb6b0f8e51e..93b2ea926df 100644 --- a/chromium/ui/base/x/x11_cursor_factory_unittest.cc +++ b/chromium/ui/base/x/x11_cursor_factory_unittest.cc @@ -20,6 +20,7 @@ TEST(X11CursorFactoryTest, InvisibleRefcount) { // CreateImageCursor should return an incremented refcount. auto* invisible_cursor = static_cast( factory.CreateImageCursor({}, SkBitmap(), gfx::Point())); + ASSERT_NE(invisible_cursor, nullptr); ASSERT_FALSE(invisible_cursor->HasOneRef()); // Release our refcount on the cursor diff --git a/chromium/ui/base/x/x11_cursor_loader.cc b/chromium/ui/base/x/x11_cursor_loader.cc index e218771aa33..90a486cd8cf 100644 --- a/chromium/ui/base/x/x11_cursor_loader.cc +++ b/chromium/ui/base/x/x11_cursor_loader.cc @@ -28,6 +28,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/task_runner_util.h" +#include "base/time/time.h" #include "ui/base/cursor/cursor_theme_manager.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/x/connection.h" @@ -325,10 +326,9 @@ scoped_refptr XCursorLoader::LoadCursor( DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto cursor = base::MakeRefCounted(); if (SupportsCreateCursor()) { - base::PostTaskAndReplyWithResult( + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, - {base::ThreadPool(), base::MayBlock(), - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce(ReadCursorImages, names, rm_xcursor_theme_, GetPreferredCursorSize()), base::BindOnce(&XCursorLoader::LoadCursorImpl, @@ -351,7 +351,7 @@ scoped_refptr XCursorLoader::CreateCursor( auto cursor = CreateCursor(image.bitmap, image.hotspot); cursors.push_back(cursor); elements.push_back(x11::Render::AnimationCursorElement{ - cursor->xcursor_, image.frame_delay_ms}); + cursor->xcursor_, image.frame_delay.InMilliseconds()}); } if (elements.empty()) @@ -584,8 +584,9 @@ std::vector ParseCursorFile( bitmap.allocN32Pixels(image.width, image.height); if (!ReadU32s(bitmap.getPixels(), bitmap.computeByteSize())) continue; - images.push_back(XCursorLoader::Image{ - bitmap, gfx::Point(image.xhot, image.yhot), image.delay}); + images.push_back( + XCursorLoader::Image{bitmap, gfx::Point(image.xhot, image.yhot), + base::TimeDelta::FromMilliseconds(image.delay)}); } return images; } diff --git a/chromium/ui/base/x/x11_cursor_loader.h b/chromium/ui/base/x/x11_cursor_loader.h index 3f7bbb6b050..6b723b82603 100644 --- a/chromium/ui/base/x/x11_cursor_loader.h +++ b/chromium/ui/base/x/x11_cursor_loader.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "base/version.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/x/x11_cursor.h" @@ -26,7 +27,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XCursorLoader { struct Image { SkBitmap bitmap; gfx::Point hotspot; - int frame_delay_ms; + base::TimeDelta frame_delay; }; explicit XCursorLoader(x11::Connection* connection); diff --git a/chromium/ui/base/x/x11_cursor_loader_unittest.cc b/chromium/ui/base/x/x11_cursor_loader_unittest.cc index 52a75c04de3..cc997bbb48d 100644 --- a/chromium/ui/base/x/x11_cursor_loader_unittest.cc +++ b/chromium/ui/base/x/x11_cursor_loader_unittest.cc @@ -66,7 +66,7 @@ TEST(XCursorLoaderTest, Basic) { }; auto images = ParseFile(&file, 1); ASSERT_EQ(images.size(), 1ul); - EXPECT_EQ(images[0].frame_delay_ms, 123); + EXPECT_EQ(images[0].frame_delay.InMilliseconds(), 123); EXPECT_EQ(images[0].bitmap.width(), 1); EXPECT_EQ(images[0].bitmap.height(), 1); EXPECT_EQ(images[0].hotspot.x(), 1234); @@ -255,8 +255,8 @@ TEST(XCursorLoaderTest, Animated) { }; auto images = ParseFile(&file, 1); ASSERT_EQ(images.size(), 2ul); - EXPECT_EQ(images[0].frame_delay_ms, 500); - EXPECT_EQ(images[1].frame_delay_ms, 500); + EXPECT_EQ(images[0].frame_delay.InMilliseconds(), 500); + EXPECT_EQ(images[1].frame_delay.InMilliseconds(), 500); } } // namespace ui diff --git a/chromium/ui/base/x/x11_desktop_window_move_client.cc b/chromium/ui/base/x/x11_desktop_window_move_client.cc index 0c53079dc0f..c420f521d9e 100644 --- a/chromium/ui/base/x/x11_desktop_window_move_client.cc +++ b/chromium/ui/base/x/x11_desktop_window_move_client.cc @@ -5,12 +5,13 @@ #include "ui/base/x/x11_desktop_window_move_client.h" #include "ui/base/x/x11_util.h" -#include "ui/base/x/x11_window.h" #include "ui/events/event.h" namespace ui { -X11DesktopWindowMoveClient::X11DesktopWindowMoveClient(ui::XWindow* window) +X11DesktopWindowMoveClient::Delegate::~Delegate() = default; + +X11DesktopWindowMoveClient::X11DesktopWindowMoveClient(Delegate* window) : window_(window) {} X11DesktopWindowMoveClient::~X11DesktopWindowMoveClient() = default; @@ -19,7 +20,7 @@ void X11DesktopWindowMoveClient::OnMouseMovement(const gfx::Point& screen_point, int flags, base::TimeTicks event_time) { gfx::Point system_loc = screen_point - window_offset_; - window_->SetBounds(gfx::Rect(system_loc, window_->bounds().size())); + window_->SetBoundsOnMove(gfx::Rect(system_loc, window_->GetSize())); } void X11DesktopWindowMoveClient::OnMouseReleased() { @@ -31,8 +32,8 @@ void X11DesktopWindowMoveClient::OnMoveLoopEnded() {} bool X11DesktopWindowMoveClient::RunMoveLoop(bool can_grab_pointer, const gfx::Vector2d& drag_offset) { window_offset_ = drag_offset; - return move_loop_.RunMoveLoop(can_grab_pointer, window_->last_cursor(), - window_->last_cursor()); + return move_loop_.RunMoveLoop(can_grab_pointer, window_->GetLastCursor(), + window_->GetLastCursor()); } void X11DesktopWindowMoveClient::EndMoveLoop() { diff --git a/chromium/ui/base/x/x11_desktop_window_move_client.h b/chromium/ui/base/x/x11_desktop_window_move_client.h index dc8462919a2..dfd8b01ae12 100644 --- a/chromium/ui/base/x/x11_desktop_window_move_client.h +++ b/chromium/ui/base/x/x11_desktop_window_move_client.h @@ -14,13 +14,25 @@ namespace ui { -class XWindow; - // When we're dragging tabs, we need to manually position our window. class COMPONENT_EXPORT(UI_BASE_X) X11DesktopWindowMoveClient : public X11MoveLoopDelegate { public: - explicit X11DesktopWindowMoveClient(ui::XWindow* window); + // Connection point that the window being moved needs to implement. + class Delegate { + public: + // Sets new window bounds. + virtual void SetBoundsOnMove(const gfx::Rect& requested_bounds) = 0; + // Returns the cursor that was used at the time the move started. + virtual scoped_refptr GetLastCursor() = 0; + // Returns the size part of the window bounds. + virtual gfx::Size GetSize() = 0; + + protected: + virtual ~Delegate(); + }; + + explicit X11DesktopWindowMoveClient(Delegate* window); ~X11DesktopWindowMoveClient() override; // Overridden from X11WholeScreenMoveLoopDelegate: @@ -38,7 +50,7 @@ class COMPONENT_EXPORT(UI_BASE_X) X11DesktopWindowMoveClient // We need to keep track of this so we can actually move it when reacting to // mouse events. - ui::XWindow* const window_; + Delegate* const window_; // Our cursor offset from the top left window origin when the drag // started. Used to calculate the window's new bounds relative to the current diff --git a/chromium/ui/base/x/x11_drag_drop_client.cc b/chromium/ui/base/x/x11_drag_drop_client.cc index b394e9ec887..91dba2f20d9 100644 --- a/chromium/ui/base/x/x11_drag_drop_client.cc +++ b/chromium/ui/base/x/x11_drag_drop_client.cc @@ -7,6 +7,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/dragdrop/drag_drop_types.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" diff --git a/chromium/ui/base/x/x11_global_shortcut_listener.cc b/chromium/ui/base/x/x11_global_shortcut_listener.cc new file mode 100644 index 00000000000..658c04c865f --- /dev/null +++ b/chromium/ui/base/x/x11_global_shortcut_listener.cc @@ -0,0 +1,148 @@ +// 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_global_shortcut_listener.h" + +#include + +#include "base/containers/contains.h" +#include "base/stl_util.h" +#include "ui/base/x/x11_util.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/platform/platform_event_source.h" +#include "ui/gfx/x/connection.h" + +namespace { + +// The modifiers masks used for grabbing keys. Due to XGrabKey only working on +// exact modifiers, we need to grab all key combinations including zero or more +// of the following: Num lock, Caps lock and Scroll lock. So that we can make +// sure the behavior of global shortcuts is consistent on all platforms. +const x11::ModMask kModifiersMasks[] = { + {}, // 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}; + +x11::ModMask GetNativeModifiers(bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) { + constexpr auto kNoMods = x11::ModMask{}; + return (is_shift_down ? x11::ModMask::Shift : kNoMods) | + (is_ctrl_down ? x11::ModMask::Control : kNoMods) | + (is_alt_down ? x11::ModMask::c_1 : kNoMods); +} + +} // namespace + +namespace ui { + +XGlobalShortcutListener::XGlobalShortcutListener() + : connection_(x11::Connection::Get()), x_root_window_(GetX11RootWindow()) {} + +XGlobalShortcutListener::~XGlobalShortcutListener() { + if (is_listening_) + StopListening(); +} + +void XGlobalShortcutListener::StartListening() { + DCHECK(!is_listening_); // Don't start twice. + DCHECK(!registered_combinations_.empty()); + + PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); + + is_listening_ = true; +} + +void XGlobalShortcutListener::StopListening() { + DCHECK(is_listening_); // No point if we are not already listening. + DCHECK(registered_combinations_.empty()); + + PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); + + is_listening_ = false; +} + +bool XGlobalShortcutListener::CanDispatchEvent(const PlatformEvent& event) { + return event->type() == ET_KEY_PRESSED; +} + +uint32_t XGlobalShortcutListener::DispatchEvent(const PlatformEvent& event) { + CHECK_EQ(event->type(), ET_KEY_PRESSED); + OnKeyPressEvent(*event->AsKeyEvent()); + return POST_DISPATCH_NONE; +} + +bool XGlobalShortcutListener::RegisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) { + auto modifiers = GetNativeModifiers(is_alt_down, is_ctrl_down, is_shift_down); + auto keysym = XKeysymForWindowsKeyCode(key_code, false); + auto keycode = connection_->KeysymToKeycode(keysym); + + // Because XGrabKey only works on the exact modifiers mask, we should register + // our hot keys with modifiers that we want to ignore, including Num lock, + // Caps lock, Scroll lock. See comment about |kModifiersMasks|. + x11::Future grab_requests[base::size(kModifiersMasks)]; + for (size_t i = 0; i < base::size(kModifiersMasks); i++) { + grab_requests[i] = connection_->GrabKey( + {false, x_root_window_, modifiers | kModifiersMasks[i], keycode, + x11::GrabMode::Async, x11::GrabMode::Async}); + } + connection_->Flush(); + for (auto& grab_request : grab_requests) { + if (grab_request.Sync().error) { + // We may have part of the hotkeys registered, clean up. + for (auto mask : kModifiersMasks) + connection_->UngrabKey({keycode, x_root_window_, modifiers | mask}); + + return false; + } + } + + registered_combinations_.insert( + Accelerator(key_code, is_alt_down, is_ctrl_down, is_shift_down)); + + return true; +} + +void XGlobalShortcutListener::UnregisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) { + auto modifiers = GetNativeModifiers(is_alt_down, is_ctrl_down, is_shift_down); + auto keysym = XKeysymForWindowsKeyCode(key_code, false); + auto keycode = connection_->KeysymToKeycode(keysym); + + for (auto mask : kModifiersMasks) + connection_->UngrabKey({keycode, x_root_window_, modifiers | mask}); + + registered_combinations_.erase( + Accelerator(key_code, is_alt_down, is_ctrl_down, is_shift_down)); +} + +void XGlobalShortcutListener::OnKeyPressEvent(const KeyEvent& event) { + DCHECK_EQ(event.type(), ET_KEY_PRESSED); + + const KeyboardCode key_code = event.key_code(); + const bool is_alt_down = event.flags() & EF_ALT_DOWN; + const bool is_ctrl_down = event.flags() & EF_CONTROL_DOWN; + const bool is_shift_down = event.flags() & EF_SHIFT_DOWN; + + if (!base::Contains( + registered_combinations_, + Accelerator(key_code, is_alt_down, is_ctrl_down, is_shift_down))) { + return; + } + + OnKeyPressed(key_code, is_alt_down, is_ctrl_down, is_shift_down); +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_global_shortcut_listener.h b/chromium/ui/base/x/x11_global_shortcut_listener.h new file mode 100644 index 00000000000..9e472d76423 --- /dev/null +++ b/chromium/ui/base/x/x11_global_shortcut_listener.h @@ -0,0 +1,81 @@ +// 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_GLOBAL_SHORTCUT_LISTENER_H_ +#define UI_BASE_X_X11_GLOBAL_SHORTCUT_LISTENER_H_ + +#include + +#include + +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/gfx/x/xproto.h" + +namespace x11 { +class Connection; +} + +namespace ui { + +class KeyEvent; + +// X11-specific implementation of the class that listens for global shortcuts. +class COMPONENT_EXPORT(UI_BASE_X) XGlobalShortcutListener + : public PlatformEventDispatcher { + public: + XGlobalShortcutListener(); + XGlobalShortcutListener(const XGlobalShortcutListener&) = delete; + XGlobalShortcutListener& operator=(const XGlobalShortcutListener&) = delete; + ~XGlobalShortcutListener() override; + + // PlatformEventDispatcher: + bool CanDispatchEvent(const PlatformEvent& event) override; + uint32_t DispatchEvent(const PlatformEvent& event) override; + + protected: + // Called when the previously registered key combination is pressed. + // The implementation should forward the output to the owner. + virtual void OnKeyPressed(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) = 0; + + void StartListening(); + void StopListening(); + bool RegisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down); + void UnregisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down); + + private: + // Due to how system key grabbing works on X11, we have to be a bit greedy and + // register combinations that we will later reject (see the comment for + // kModifiersMasks in the cc file). For that we store registered combinations + // and filter the incoming events against that registry before notifying the + // observer. This tuple describes the meaningful parts of the event; booleans + // 1, 2, and 3 hold states of Alt, Control, and Shift keys, respectively. + using Accelerator = std::tuple; + + // Invoked when a global shortcut is pressed. + void OnKeyPressEvent(const KeyEvent& event); + + // Whether this object is listening for global shortcuts. + bool is_listening_ = false; + + // Key combinations that we are interested in. + std::set registered_combinations_; + + // The x11 default display and the native root window. + x11::Connection* connection_; + x11::Window x_root_window_; +}; + +} // namespace ui + +#endif // UI_BASE_X_X11_GLOBAL_SHORTCUT_LISTENER_H_ diff --git a/chromium/ui/base/x/x11_menu_registrar.h b/chromium/ui/base/x/x11_menu_registrar.h index 3d5c68da1d5..69f0e4d56f2 100644 --- a/chromium/ui/base/x/x11_menu_registrar.h +++ b/chromium/ui/base/x/x11_menu_registrar.h @@ -11,6 +11,7 @@ #include #include +#include "base/component_export.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/event.h" @@ -23,7 +24,7 @@ namespace ui { // A singleton that owns global objects related to the desktop and listens for // X11 events on the X11 root window. Destroys itself when the browser // shuts down. -class X11MenuRegistrar : public x11::EventObserver { +class COMPONENT_EXPORT(UI_BASE_X) X11MenuRegistrar : public x11::EventObserver { public: // Returns the singleton handler. Creates one if one has not // already been created. diff --git a/chromium/ui/base/x/x11_os_exchange_data_provider.cc b/chromium/ui/base/x/x11_os_exchange_data_provider.cc index 78d2b362c2d..cbf6e7f50b8 100644 --- a/chromium/ui/base/x/x11_os_exchange_data_provider.cc +++ b/chromium/ui/base/x/x11_os_exchange_data_provider.cc @@ -90,7 +90,7 @@ bool XOSExchangeDataProvider::DidOriginateFromRenderer() const { return format_map_.find(x11::GetAtom(kRendererTaint)) != format_map_.end(); } -void XOSExchangeDataProvider::SetString(const base::string16& text_data) { +void XOSExchangeDataProvider::SetString(const std::u16string& text_data) { if (HasString()) return; @@ -105,16 +105,16 @@ void XOSExchangeDataProvider::SetString(const base::string16& text_data) { } void XOSExchangeDataProvider::SetURL(const GURL& url, - const base::string16& title) { + const std::u16string& title) { // TODO(dcheng): The original GTK code tries very hard to avoid writing out an // empty title. Is this necessary? if (url.is_valid()) { // Mozilla's URL format: (UTF16: URL, newline, title) - base::string16 spec = base::UTF8ToUTF16(url.spec()); + std::u16string spec = base::UTF8ToUTF16(url.spec()); std::vector data; ui::AddString16ToVector(spec, &data); - ui::AddString16ToVector(base::ASCIIToUTF16("\n"), &data); + ui::AddString16ToVector(u"\n", &data); ui::AddString16ToVector(title, &data); scoped_refptr mem( base::RefCountedBytes::TakeVector(&data)); @@ -179,7 +179,7 @@ void XOSExchangeDataProvider::SetPickledData(const ClipboardFormatType& format, format_map_.Insert(x11::GetAtom(format.GetName().c_str()), mem); } -bool XOSExchangeDataProvider::GetString(base::string16* result) const { +bool XOSExchangeDataProvider::GetString(std::u16string* result) const { if (HasFile()) { // Various Linux file managers both pass a list of file:// URIs and set the // string representation to the URI. We explicitly don't want to return use @@ -203,7 +203,7 @@ bool XOSExchangeDataProvider::GetString(base::string16* result) const { bool XOSExchangeDataProvider::GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const { + std::u16string* title) const { std::vector url_atoms = ui::GetURLAtomsFrom(); std::vector requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); @@ -216,17 +216,16 @@ bool XOSExchangeDataProvider::GetURLAndTitle(FilenameToURLPolicy policy, if (data.GetType() == x11::GetAtom(kMimeTypeMozillaURL)) { // Mozilla URLs are (UTF16: URL, newline, title). - base::string16 unparsed; + std::u16string unparsed; data.AssignTo(&unparsed); - std::vector tokens = - base::SplitString(unparsed, base::ASCIIToUTF16("\n"), - base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + std::vector tokens = base::SplitString( + unparsed, u"\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); if (tokens.size() > 0) { if (tokens.size() > 1) *title = tokens[1]; else - *title = base::string16(); + *title = std::u16string(); *url = GURL(tokens[0]); return true; @@ -238,7 +237,7 @@ bool XOSExchangeDataProvider::GetURLAndTitle(FilenameToURLPolicy policy, if (!test_url.SchemeIsFile() || policy == FilenameToURLPolicy::CONVERT_FILENAMES) { *url = test_url; - *title = base::string16(); + *title = std::u16string(); return true; } } @@ -400,7 +399,19 @@ void XOSExchangeDataProvider::SetFileContents( base::RefCountedString::TakeString(&file_contents_copy))); } -void XOSExchangeDataProvider::SetHtml(const base::string16& html, +bool XOSExchangeDataProvider::GetFileContents( + base::FilePath* filename, + std::string* file_contents) const { + NOTIMPLEMENTED(); + return false; +} + +bool XOSExchangeDataProvider::HasFileContents() const { + NOTIMPLEMENTED(); + return false; +} + +void XOSExchangeDataProvider::SetHtml(const std::u16string& html, const GURL& base_url) { std::vector bytes; // Manually jam a UTF16 BOM into bytes because otherwise, other programs will @@ -414,7 +425,7 @@ void XOSExchangeDataProvider::SetHtml(const base::string16& html, format_map_.Insert(x11::GetAtom(kMimeTypeHTML), mem); } -bool XOSExchangeDataProvider::GetHtml(base::string16* html, +bool XOSExchangeDataProvider::GetHtml(std::u16string* html, GURL* base_url) const { std::vector url_atoms; url_atoms.push_back(x11::GetAtom(kMimeTypeHTML)); @@ -455,7 +466,7 @@ gfx::Vector2d XOSExchangeDataProvider::GetDragImageOffset() const { } bool XOSExchangeDataProvider::GetPlainTextURL(GURL* url) const { - base::string16 text; + std::u16string text; if (GetString(&text)) { GURL test_url(text); if (test_url.is_valid()) { diff --git a/chromium/ui/base/x/x11_os_exchange_data_provider.h b/chromium/ui/base/x/x11_os_exchange_data_provider.h index fbc79e53b91..ea419cf93de 100644 --- a/chromium/ui/base/x/x11_os_exchange_data_provider.h +++ b/chromium/ui/base/x/x11_os_exchange_data_provider.h @@ -63,16 +63,16 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider std::unique_ptr Clone() const override; void MarkOriginatedFromRenderer() override; bool DidOriginateFromRenderer() const override; - void SetString(const base::string16& data) override; - void SetURL(const GURL& url, const base::string16& title) override; + void SetString(const std::u16string& data) override; + void SetURL(const GURL& url, const std::u16string& title) override; void SetFilename(const base::FilePath& path) override; void SetFilenames(const std::vector& filenames) override; void SetPickledData(const ClipboardFormatType& format, const base::Pickle& pickle) override; - bool GetString(base::string16* data) const override; + bool GetString(std::u16string* data) const override; bool GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, - base::string16* title) const override; + std::u16string* title) const override; bool GetFilename(base::FilePath* path) const override; bool GetFilenames(std::vector* filenames) const override; bool GetPickledData(const ClipboardFormatType& format, @@ -83,9 +83,12 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider bool HasCustomFormat(const ClipboardFormatType& format) const override; void SetFileContents(const base::FilePath& filename, const std::string& file_contents) override; + bool GetFileContents(base::FilePath* filename, + std::string* file_contents) const override; + bool HasFileContents() const override; - void SetHtml(const base::string16& html, const GURL& base_url) override; - bool GetHtml(base::string16* html, GURL* base_url) const override; + void SetHtml(const std::u16string& html, const GURL& base_url) override; + bool GetHtml(std::u16string* html, GURL* base_url) const override; bool HasHtml() const override; void SetDragImage(const gfx::ImageSkia& image, const gfx::Vector2d& cursor_offset) override; diff --git a/chromium/ui/base/x/x11_user_input_monitor.cc b/chromium/ui/base/x/x11_user_input_monitor.cc index 192bd704f5f..8b6b702bd17 100644 --- a/chromium/ui/base/x/x11_user_input_monitor.cc +++ b/chromium/ui/base/x/x11_user_input_monitor.cc @@ -79,7 +79,7 @@ void XUserInputMonitor::StartMonitor(WriteKeyPressCallback& callback) { connection_->xinput().XIQueryVersion( {x11::Input::major_version, x11::Input::minor_version}); - x11::Input::XIEventMask mask; + x11::Input::XIEventMask mask{}; SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyPress); SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyRelease); connection_->xinput().XISelectEvents( diff --git a/chromium/ui/base/x/x11_util.cc b/chromium/ui/base/x/x11_util.cc index 130708ac2e2..2efcfb9f456 100644 --- a/chromium/ui/base/x/x11_util.cc +++ b/chromium/ui/base/x/x11_util.cc @@ -951,31 +951,19 @@ void SuspendX11ScreenSaver(bool suspend) { x11::Connection::Get()->screensaver().Suspend({suspend}); } -base::Value GpuExtraInfoAsListValue(x11::VisualId system_visual, - x11::VisualId rgba_visual) { - base::Value result(base::Value::Type::LIST); - result.Append( +void StoreGpuExtraInfoIntoListValue(x11::VisualId system_visual, + x11::VisualId rgba_visual, + base::Value& list_value) { + list_value.Append( NewDescriptionValuePair("Window manager", ui::GuessWindowManagerName())); - { - std::unique_ptr env(base::Environment::Create()); - std::string value; - const char kXDGCurrentDesktop[] = "XDG_CURRENT_DESKTOP"; - if (env->GetVar(kXDGCurrentDesktop, &value)) - result.Append(NewDescriptionValuePair(kXDGCurrentDesktop, value)); - const char kGDMSession[] = "GDMSESSION"; - if (env->GetVar(kGDMSession, &value)) - result.Append(NewDescriptionValuePair(kGDMSession, value)); - result.Append(NewDescriptionValuePair( - "Compositing manager", - ui::IsCompositingManagerPresent() ? "Yes" : "No")); - } - result.Append(NewDescriptionValuePair( + list_value.Append(NewDescriptionValuePair( + "Compositing manager", ui::IsCompositingManagerPresent() ? "Yes" : "No")); + list_value.Append(NewDescriptionValuePair( "System visual ID", base::NumberToString(static_cast(system_visual)))); - result.Append(NewDescriptionValuePair( + list_value.Append(NewDescriptionValuePair( "RGBA visual ID", base::NumberToString(static_cast(rgba_visual)))); - return result; } bool WmSupportsHint(x11::Atom atom) { @@ -1108,6 +1096,49 @@ bool DoesVisualHaveAlphaForTest() { return visual_has_alpha; } +gfx::ImageSkia GetNativeWindowIcon(intptr_t target_window_id) { + std::vector data; + if (!GetArrayProperty(static_cast(target_window_id), + x11::GetAtom("_NET_WM_ICON"), &data)) { + return gfx::ImageSkia(); + } + + // The format of |data| is concatenation of sections like + // [width, height, pixel data of size width * height], and the total bytes + // number of |data| is |size|. And here we are picking the largest icon. + int width = 0; + int height = 0; + int start = 0; + size_t i = 0; + while (i + 1 < data.size()) { + if ((static_cast(data[i] * data[i + 1]) > width * height) && + (i + 1 + data[i] * data[i + 1] < data.size())) { + width = static_cast(data[i]); + height = static_cast(data[i + 1]); + start = i + 2; + } + i += 2 + static_cast(data[i] * data[i + 1]); + } + + if (width == 0 || height == 0) + return gfx::ImageSkia(); + + SkBitmap result; + SkImageInfo info = SkImageInfo::MakeN32(width, height, kUnpremul_SkAlphaType); + result.allocPixels(info); + + uint32_t* pixels_data = reinterpret_cast(result.getPixels()); + + for (long y = 0; y < height; ++y) { + for (long x = 0; x < width; ++x) { + pixels_data[result.rowBytesAsPixels() * y + x] = + static_cast(data[start + width * y + x]); + } + } + + return gfx::ImageSkia::CreateFrom1xBitmap(result); +} + // static XVisualManager* XVisualManager::GetInstance() { return base::Singleton::get(); diff --git a/chromium/ui/base/x/x11_util.h b/chromium/ui/base/x/x11_util.h index 450525f41b5..fc3f2d9360b 100644 --- a/chromium/ui/base/x/x11_util.h +++ b/chromium/ui/base/x/x11_util.h @@ -8,6 +8,7 @@ // This file declares utility functions for X11 (Linux only). #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/platform_event.h" #include "ui/gfx/icc_profile.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/event.h" #include "ui/gfx/x/future.h" @@ -38,6 +40,7 @@ class SkPixmap; namespace base { template struct DefaultSingletonTraits; +class Value; } namespace gfx { @@ -399,8 +402,9 @@ 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) -base::Value GpuExtraInfoAsListValue(x11::VisualId system_visual, - x11::VisualId rgba_visual); +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,6 +437,11 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsVulkanSurfaceSupported(); // The function examines the _CHROMIUM_INSIDE_XVFB environment variable. COMPONENT_EXPORT(UI_BASE_X) bool DoesVisualHaveAlphaForTest(); +// Returns an icon for a native window referred by |target_window_id|. Can be +// any window on screen. +COMPONENT_EXPORT(UI_BASE_X) +gfx::ImageSkia GetNativeWindowIcon(intptr_t target_window_id); + // -------------------------------------------------------------------------- // Selects a visual with a preference for alpha support on compositing window // managers. diff --git a/chromium/ui/base/x/x11_window.cc b/chromium/ui/base/x/x11_window.cc deleted file mode 100644 index 585a09a2b6d..00000000000 --- a/chromium/ui/base/x/x11_window.cc +++ /dev/null @@ -1,1576 +0,0 @@ -// 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/x/x11_window.h" - -#include -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "build/chromeos_buildflags.h" -#include "net/base/network_interfaces.h" -#include "third_party/skia/include/core/SkRegion.h" -#include "ui/base/hit_test_x11.h" -#include "ui/base/ui_base_features.h" -#include "ui/base/wm_role_names_linux.h" -#include "ui/base/x/x11_menu_registrar.h" -#include "ui/base/x/x11_pointer_grab.h" -#include "ui/base/x/x11_util.h" -#include "ui/events/devices/x11/device_data_manager_x11.h" -#include "ui/events/devices/x11/touch_factory_x11.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/events/platform/x11/x11_event_source.h" -#include "ui/events/x/events_x_utils.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/image/image_skia_rep.h" -#include "ui/gfx/skia_util.h" -#include "ui/gfx/x/connection.h" -#include "ui/gfx/x/x11_atom_cache.h" -#include "ui/gfx/x/x11_path.h" -#include "ui/gfx/x/x11_window_event_manager.h" -#include "ui/gfx/x/xfixes.h" -#include "ui/gfx/x/xinput.h" -#include "ui/gfx/x/xproto.h" -#include "ui/gfx/x/xproto_util.h" -#include "ui/platform_window/common/platform_window_defaults.h" - -namespace ui { - -namespace { - -// Special value of the _NET_WM_DESKTOP property which indicates that the window -// should appear on all workspaces/desktops. -const int32_t kAllWorkspaces = -1; - -constexpr char kX11WindowRolePopup[] = "popup"; -constexpr char kX11WindowRoleBubble[] = "bubble"; -constexpr char kDarkGtkThemeVariant[] = "dark"; - -constexpr long kSystemTrayRequestDock = 0; - -constexpr int kXembedInfoProtocolVersion = 0; -constexpr int kXembedFlagMap = 1 << 0; -constexpr int kXembedInfoFlags = kXembedFlagMap; - -enum CrossingFlags : uint8_t { - CROSSING_FLAG_FOCUS = 1 << 0, - CROSSING_FLAG_SAME_SCREEN = 1 << 1, -}; - -// In some situations, views tries to make a zero sized window, and that -// makes us crash. Make sure we have valid sizes. -gfx::Rect SanitizeBounds(const gfx::Rect& bounds) { - gfx::Size sanitized_size(std::max(bounds.width(), 1), - std::max(bounds.height(), 1)); - gfx::Rect sanitized_bounds(bounds.origin(), sanitized_size); - return sanitized_bounds; -} - -void SerializeImageRepresentation(const gfx::ImageSkiaRep& rep, - std::vector* data) { - uint32_t width = rep.GetWidth(); - data->push_back(width); - - uint32_t height = rep.GetHeight(); - data->push_back(height); - - const SkBitmap& bitmap = rep.GetBitmap(); - - for (uint32_t y = 0; y < height; ++y) - for (uint32_t x = 0; x < width; ++x) - data->push_back(bitmap.getColor(x, y)); -} - -x11::NotifyMode XI2ModeToXMode(x11::Input::NotifyMode xi2_mode) { - switch (xi2_mode) { - case x11::Input::NotifyMode::Normal: - return x11::NotifyMode::Normal; - case x11::Input::NotifyMode::Grab: - case x11::Input::NotifyMode::PassiveGrab: - return x11::NotifyMode::Grab; - case x11::Input::NotifyMode::Ungrab: - case x11::Input::NotifyMode::PassiveUngrab: - return x11::NotifyMode::Ungrab; - case x11::Input::NotifyMode::WhileGrabbed: - return x11::NotifyMode::WhileGrabbed; - default: - NOTREACHED(); - return x11::NotifyMode::Normal; - } -} - -x11::NotifyDetail XI2DetailToXDetail(x11::Input::NotifyDetail xi2_detail) { - switch (xi2_detail) { - case x11::Input::NotifyDetail::Ancestor: - return x11::NotifyDetail::Ancestor; - case x11::Input::NotifyDetail::Virtual: - return x11::NotifyDetail::Virtual; - case x11::Input::NotifyDetail::Inferior: - return x11::NotifyDetail::Inferior; - case x11::Input::NotifyDetail::Nonlinear: - return x11::NotifyDetail::Nonlinear; - case x11::Input::NotifyDetail::NonlinearVirtual: - return x11::NotifyDetail::NonlinearVirtual; - case x11::Input::NotifyDetail::Pointer: - return x11::NotifyDetail::Pointer; - case x11::Input::NotifyDetail::PointerRoot: - return x11::NotifyDetail::PointerRoot; - case x11::Input::NotifyDetail::None: - return x11::NotifyDetail::None; - } -} - -void SyncSetCounter(x11::Connection* connection, - x11::Sync::Counter counter, - int64_t value) { - x11::Sync::Int64 sync_value{.hi = value >> 32, .lo = value & 0xFFFFFFFF}; - connection->sync().SetCounter({counter, sync_value}); -} - -// Returns the whole path from |window| to the root. -std::vector GetParentsList(x11::Connection* connection, - x11::Window window) { - std::vector result; - while (window != x11::Window::None) { - result.push_back(window); - if (auto reply = connection->QueryTree({window}).Sync()) - window = reply->parent; - else - break; - } - return result; -} - -} // namespace - -XWindow::Configuration::Configuration() - : type(WindowType::kWindow), - opacity(WindowOpacity::kInferOpacity), - icon(nullptr), - activatable(true), - force_show_in_taskbar(false), - keep_on_top(false), - visible_on_all_workspaces(false), - remove_standard_frame(true), - prefer_dark_theme(false) {} - -XWindow::Configuration::Configuration(const Configuration&) = default; - -XWindow::Configuration::~Configuration() = default; - -XWindow::XWindow() - : connection_(x11::Connection::Get()), x_root_window_(GetX11RootWindow()) { - DCHECK(connection_); - DCHECK_NE(x_root_window_, x11::Window::None); -} - -XWindow::~XWindow() { - DCHECK_EQ(xwindow_, x11::Window::None) - << "XWindow destructed without calling " - "Close() to release allocated resources."; -} - -void XWindow::Init(const Configuration& config) { - // Ensure that the X11MenuRegistrar exists. The X11MenuRegistrar is - // necessary to properly track menu windows. - X11MenuRegistrar::Get(); - - activatable_ = config.activatable; - - x11::CreateWindowRequest req; - req.bit_gravity = x11::Gravity::NorthWest; - req.background_pixel = config.background_color.has_value() - ? config.background_color.value() - : connection_->default_screen().white_pixel; - - x11::Atom window_type; - switch (config.type) { - case WindowType::kMenu: - req.override_redirect = x11::Bool32(true); - window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_MENU"); - break; - case WindowType::kTooltip: - req.override_redirect = x11::Bool32(true); - window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"); - break; - case WindowType::kPopup: - req.override_redirect = x11::Bool32(true); - window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION"); - break; - case WindowType::kDrag: - req.override_redirect = x11::Bool32(true); - window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_DND"); - break; - default: - window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_NORMAL"); - break; - } - // An in-activatable window should not interact with the system wm. - if (!activatable_ || config.override_redirect) - req.override_redirect = x11::Bool32(true); - -#if BUILDFLAG(IS_CHROMEOS_ASH) - req.override_redirect = x11::Bool32(UseTestConfigForPlatformWindows()); -#endif - - override_redirect_ = req.override_redirect.has_value(); - - bool enable_transparent_visuals; - switch (config.opacity) { - case WindowOpacity::kOpaqueWindow: - enable_transparent_visuals = false; - break; - case WindowOpacity::kTranslucentWindow: - enable_transparent_visuals = true; - break; - case WindowOpacity::kInferOpacity: - enable_transparent_visuals = config.type == WindowType::kDrag; - } - - if (config.wm_role_name == kStatusIconWmRoleName) { - std::string atom_name = - "_NET_SYSTEM_TRAY_S" + - base::NumberToString(connection_->DefaultScreenId()); - auto selection = connection_->GetSelectionOwner({x11::GetAtom(atom_name)}); - if (auto reply = selection.Sync()) { - GetProperty(reply->owner, x11::GetAtom("_NET_SYSTEM_TRAY_VISUAL"), - &visual_id_); - } - } - - x11::VisualId visual_id = visual_id_; - uint8_t depth = 0; - x11::ColorMap colormap{}; - XVisualManager* visual_manager = XVisualManager::GetInstance(); - if (visual_id_ == x11::VisualId{} || - !visual_manager->GetVisualInfo(visual_id_, &depth, &colormap, - &visual_has_alpha_)) { - visual_manager->ChooseVisualForWindow(enable_transparent_visuals, - &visual_id, &depth, &colormap, - &visual_has_alpha_); - } - - // x.org will BadMatch if we don't set a border when the depth isn't the - // same as the parent depth. - req.border_pixel = 0; - - bounds_in_pixels_ = SanitizeBounds(config.bounds); - req.parent = x_root_window_; - req.x = bounds_in_pixels_.x(); - req.y = bounds_in_pixels_.y(); - req.width = bounds_in_pixels_.width(); - req.height = bounds_in_pixels_.height(); - req.depth = depth; - req.c_class = x11::WindowClass::InputOutput; - req.visual = visual_id; - req.colormap = colormap; - xwindow_ = connection_->GenerateId(); - req.wid = xwindow_; - connection_->CreateWindow(req); - - // It can be a status icon window. If it fails to initialize, don't provide - // him with a native window handle, close self and let the client destroy - // ourselves. - if (config.wm_role_name == kStatusIconWmRoleName && - !InitializeAsStatusIcon()) { - Close(); - return; - } - - OnXWindowCreated(); - - // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). - - auto event_mask = - x11::EventMask::ButtonPress | x11::EventMask::ButtonRelease | - x11::EventMask::FocusChange | x11::EventMask::KeyPress | - x11::EventMask::KeyRelease | x11::EventMask::EnterWindow | - x11::EventMask::LeaveWindow | x11::EventMask::Exposure | - x11::EventMask::VisibilityChange | x11::EventMask::StructureNotify | - x11::EventMask::PropertyChange | x11::EventMask::PointerMotion; - xwindow_events_ = - std::make_unique(xwindow_, event_mask); - connection_->Flush(); - - if (IsXInput2Available()) - TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); - - // Request the _NET_WM_SYNC_REQUEST protocol which is used for synchronizing - // between chrome and desktop compositor (or WM) during resizing. - // The resizing behavior with _NET_WM_SYNC_REQUEST is: - // 1. Desktop compositor (or WM) sends client message _NET_WM_SYNC_REQUEST - // with a 64 bits counter to notify about an incoming resize. - // 2. Desktop compositor resizes chrome browser window. - // 3. Desktop compositor waits on an alert on value change of XSyncCounter on - // chrome window. - // 4. Chrome handles the ConfigureNotify event, and renders a new frame with - // the new size. - // 5. Chrome increases the XSyncCounter on chrome window - // 6. Desktop compositor gets the alert of counter change, and draws a new - // frame with new content from chrome. - // 7. Desktop compositor responses user mouse move events, and starts a new - // resize process, go to step 1. - std::vector protocols = { - x11::GetAtom("WM_DELETE_WINDOW"), - x11::GetAtom("_NET_WM_PING"), - x11::GetAtom("_NET_WM_SYNC_REQUEST"), - }; - SetArrayProperty(xwindow_, x11::GetAtom("WM_PROTOCOLS"), x11::Atom::ATOM, - protocols); - - // We need a WM_CLIENT_MACHINE value so we integrate with the desktop - // environment. - SetStringProperty(xwindow_, x11::Atom::WM_CLIENT_MACHINE, x11::Atom::STRING, - net::GetHostName()); - - // Likewise, the X server needs to know this window's pid so it knows which - // program to kill if the window hangs. - // XChangeProperty() expects "pid" to be long. - static_assert(sizeof(uint32_t) >= sizeof(pid_t), - "pid_t should not be larger than uint32_t"); - uint32_t pid = getpid(); - SetProperty(xwindow_, x11::GetAtom("_NET_WM_PID"), x11::Atom::CARDINAL, pid); - - SetProperty(xwindow_, x11::GetAtom("_NET_WM_WINDOW_TYPE"), x11::Atom::ATOM, - window_type); - - // The changes to |window_properties_| here will be sent to the X server just - // before the window is mapped. - - // Remove popup windows from taskbar unless overridden. - if ((config.type == WindowType::kPopup || - config.type == WindowType::kBubble) && - !config.force_show_in_taskbar) { - window_properties_.insert(x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); - } - - // If the window should stay on top of other windows, add the - // _NET_WM_STATE_ABOVE property. - is_always_on_top_ = config.keep_on_top; - if (is_always_on_top_) - window_properties_.insert(x11::GetAtom("_NET_WM_STATE_ABOVE")); - - workspace_ = base::nullopt; - if (config.visible_on_all_workspaces) { - window_properties_.insert(x11::GetAtom("_NET_WM_STATE_STICKY")); - SetProperty(xwindow_, x11::GetAtom("_NET_WM_DESKTOP"), x11::Atom::CARDINAL, - kAllWorkspaces); - } else if (!config.workspace.empty()) { - int32_t workspace; - if (base::StringToInt(config.workspace, &workspace)) - SetProperty(xwindow_, x11::GetAtom("_NET_WM_DESKTOP"), - x11::Atom::CARDINAL, workspace); - } - - if (!config.wm_class_name.empty() || !config.wm_class_class.empty()) { - SetWindowClassHint(connection_, xwindow_, config.wm_class_name, - config.wm_class_class); - } - - const char* wm_role_name = nullptr; - // If the widget isn't overriding the role, provide a default value for popup - // and bubble types. - if (!config.wm_role_name.empty()) { - wm_role_name = config.wm_role_name.c_str(); - } else { - switch (config.type) { - case WindowType::kPopup: - wm_role_name = kX11WindowRolePopup; - break; - case WindowType::kBubble: - wm_role_name = kX11WindowRoleBubble; - break; - default: - break; - } - } - if (wm_role_name) - SetWindowRole(xwindow_, std::string(wm_role_name)); - - if (config.remove_standard_frame) { - // Setting _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED tells gnome-shell to not force - // fullscreen on the window when it matches the desktop size. - SetHideTitlebarWhenMaximizedProperty(xwindow_, - HIDE_TITLEBAR_WHEN_MAXIMIZED); - } - - if (config.prefer_dark_theme) { - SetStringProperty(xwindow_, x11::GetAtom("_GTK_THEME_VARIANT"), - x11::GetAtom("UTF8_STRING"), kDarkGtkThemeVariant); - } - - if (IsSyncExtensionAvailable()) { - x11::Sync::Int64 value{}; - update_counter_ = connection_->GenerateId(); - connection_->sync().CreateCounter({update_counter_, value}); - extended_update_counter_ = connection_->GenerateId(); - connection_->sync().CreateCounter({extended_update_counter_, value}); - - std::vector counters{update_counter_, - extended_update_counter_}; - - // Set XSyncCounter as window property _NET_WM_SYNC_REQUEST_COUNTER. the - // compositor will listen on them during resizing. - SetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_SYNC_REQUEST_COUNTER"), - x11::Atom::CARDINAL, counters); - } - - // Always composite Chromium windows if a compositing WM is used. Sometimes, - // WMs will not composite fullscreen windows as an optimization, but this can - // lead to tearing of fullscreen videos. - x11::SetProperty(xwindow_, - x11::GetAtom("_NET_WM_BYPASS_COMPOSITOR"), - x11::Atom::CARDINAL, 2); - - if (config.icon) - SetXWindowIcons(gfx::ImageSkia(), *config.icon); -} - -void XWindow::Map(bool inactive) { - // Before we map the window, set size hints. Otherwise, some window managers - // will ignore toplevel XMoveWindow commands. - SizeHints size_hints; - memset(&size_hints, 0, sizeof(size_hints)); - GetWmNormalHints(xwindow_, &size_hints); - size_hints.flags |= SIZE_HINT_P_POSITION; - size_hints.x = bounds_in_pixels_.x(); - size_hints.y = bounds_in_pixels_.y(); - SetWmNormalHints(xwindow_, size_hints); - - ignore_keyboard_input_ = inactive; - auto wm_user_time_ms = ignore_keyboard_input_ - ? x11::Time::CurrentTime - : X11EventSource::GetInstance()->GetTimestamp(); - if (inactive || wm_user_time_ms != x11::Time::CurrentTime) { - SetProperty(xwindow_, x11::GetAtom("_NET_WM_USER_TIME"), - x11::Atom::CARDINAL, wm_user_time_ms); - } - - UpdateMinAndMaxSize(); - - if (window_properties_.empty()) { - x11::DeleteProperty(xwindow_, x11::GetAtom("_NET_WM_STATE")); - } else { - SetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_STATE"), x11::Atom::ATOM, - std::vector(std::begin(window_properties_), - std::end(window_properties_))); - } - - connection_->MapWindow({xwindow_}); - window_mapped_in_client_ = true; - - // TODO(thomasanderson): Find out why this flush is necessary. - connection_->Flush(); -} - -void XWindow::Close() { - if (xwindow_ == x11::Window::None) - return; - - CancelResize(); - UnconfineCursor(); - - connection_->DestroyWindow({xwindow_}); - xwindow_ = x11::Window::None; - - if (update_counter_ != x11::Sync::Counter{}) { - connection_->sync().DestroyCounter({update_counter_}); - connection_->sync().DestroyCounter({extended_update_counter_}); - update_counter_ = {}; - extended_update_counter_ = {}; - } -} - -void XWindow::Maximize() { - // Some WMs do not respect maximization hints on unmapped windows, so we - // save this one for later too. - should_maximize_after_map_ = !window_mapped_in_client_; - - SetWMSpecState(true, x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), - x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")); -} - -void XWindow::Minimize() { - if (window_mapped_in_client_) { - SendClientMessage(xwindow_, x_root_window_, x11::GetAtom("WM_CHANGE_STATE"), - {WM_STATE_ICONIC, 0, 0, 0, 0}); - } else { - SetWMSpecState(true, x11::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None); - } -} - -void XWindow::Unmaximize() { - should_maximize_after_map_ = false; - SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), - x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")); -} - -bool XWindow::Hide() { - if (!window_mapped_in_client_) - return false; - - // Make sure no resize task will run after the window is unmapped. - CancelResize(); - - WithdrawWindow(xwindow_); - window_mapped_in_client_ = false; - return true; -} - -void XWindow::Unhide() { - SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None); -} - -void XWindow::SetFullscreen(bool fullscreen) { - SetWMSpecState(fullscreen, x11::GetAtom("_NET_WM_STATE_FULLSCREEN"), - x11::Atom::None); -} - -void XWindow::Activate() { - if (!IsXWindowVisible() || !activatable_) - return; - - BeforeActivationStateChanged(); - - ignore_keyboard_input_ = false; - - // wmii says that it supports _NET_ACTIVE_WINDOW but does not. - // https://code.google.com/p/wmii/issues/detail?id=266 - static bool wm_supports_active_window = - GuessWindowManager() != WM_WMII && - WmSupportsHint(x11::GetAtom("_NET_ACTIVE_WINDOW")); - - x11::Time timestamp = X11EventSource::GetInstance()->GetTimestamp(); - - // override_redirect windows ignore _NET_ACTIVE_WINDOW. - // https://crbug.com/940924 - if (wm_supports_active_window && !override_redirect_) { - std::array data = { - // We're an app. - 1, - static_cast(timestamp), - // TODO(thomasanderson): if another chrome window is active, specify - // that here. The EWMH spec claims this may make the WM more likely to - // service our _NET_ACTIVE_WINDOW request. - 0, - 0, - 0, - }; - SendClientMessage(xwindow_, x_root_window_, - x11::GetAtom("_NET_ACTIVE_WINDOW"), data); - } else { - RaiseWindow(xwindow_); - // Directly ask the X server to give focus to the window. Note that the call - // would have raised an X error if the window is not mapped. - connection_ - ->SetInputFocus({x11::InputFocus::Parent, xwindow_, - static_cast(timestamp)}) - .IgnoreError(); - // At this point, we know we will receive focus, and some webdriver tests - // depend on a window being IsActive() immediately after an Activate(), so - // just set this state now. - has_pointer_focus_ = false; - has_window_focus_ = true; - window_mapped_in_server_ = true; - } - - AfterActivationStateChanged(); -} - -void XWindow::Deactivate() { - BeforeActivationStateChanged(); - - // Ignore future input events. - ignore_keyboard_input_ = true; - - ui::LowerWindow(xwindow_); - - AfterActivationStateChanged(); -} - -bool XWindow::IsActive() const { - // Focus and stacking order are independent in X11. Since we cannot guarantee - // a window is topmost iff it has focus, just use the focus state to determine - // if a window is active. Note that Activate() and Deactivate() change the - // stacking order in addition to changing the focus state. - return (has_window_focus_ || has_pointer_focus_) && !ignore_keyboard_input_; -} - -void XWindow::SetSize(const gfx::Size& size_in_pixels) { - connection_->ConfigureWindow({.window = xwindow_, - .width = size_in_pixels.width(), - .height = size_in_pixels.height()}); - bounds_in_pixels_.set_size(size_in_pixels); -} - -void XWindow::SetBounds(const gfx::Rect& requested_bounds_in_pixels) { - gfx::Rect bounds_in_pixels(requested_bounds_in_pixels); - bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin(); - bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size(); - - x11::ConfigureWindowRequest req{.window = xwindow_}; - - if (size_changed) { - // Update the minimum and maximum sizes in case they have changed. - UpdateMinAndMaxSize(); - - if (bounds_in_pixels.width() < min_size_in_pixels_.width() || - bounds_in_pixels.height() < min_size_in_pixels_.height() || - (!max_size_in_pixels_.IsEmpty() && - (bounds_in_pixels.width() > max_size_in_pixels_.width() || - bounds_in_pixels.height() > max_size_in_pixels_.height()))) { - gfx::Size size_in_pixels = bounds_in_pixels.size(); - if (!max_size_in_pixels_.IsEmpty()) - size_in_pixels.SetToMin(max_size_in_pixels_); - size_in_pixels.SetToMax(min_size_in_pixels_); - bounds_in_pixels.set_size(size_in_pixels); - } - - req.width = bounds_in_pixels.width(); - req.height = bounds_in_pixels.height(); - } - - if (origin_changed) { - req.x = bounds_in_pixels.x(); - req.y = bounds_in_pixels.y(); - } - - if (origin_changed || size_changed) - connection_->ConfigureWindow(req); - - // Assume that the resize will go through as requested, which should be the - // case if we're running without a window manager. If there's a window - // manager, it can modify or ignore the request, but (per ICCCM) we'll get a - // (possibly synthetic) ConfigureNotify about the actual size and correct - // |bounds_in_pixels_| later. - bounds_in_pixels_ = bounds_in_pixels; - ResetWindowRegion(); - - // Even if the pixel bounds didn't change this call to the delegate should - // still happen. The device scale factor may have changed which effectively - // changes the bounds. - OnXWindowBoundsChanged(bounds_in_pixels); -} - -bool XWindow::IsXWindowVisible() const { - // On Windows, IsVisible() returns true for minimized windows. On X11, a - // minimized window is not mapped, so an explicit IsMinimized() check is - // necessary. - return window_mapped_in_client_ || IsMinimized(); -} - -bool XWindow::IsMinimized() const { - return HasWMSpecProperty(window_properties_, - x11::GetAtom("_NET_WM_STATE_HIDDEN")); -} - -bool XWindow::IsMaximized() const { - return (HasWMSpecProperty(window_properties_, - x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) && - HasWMSpecProperty(window_properties_, - x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"))); -} - -bool XWindow::IsFullscreen() const { - return HasWMSpecProperty(window_properties_, - x11::GetAtom("_NET_WM_STATE_FULLSCREEN")); -} - -gfx::Rect XWindow::GetOuterBounds() const { - gfx::Rect outer_bounds(bounds_in_pixels_); - outer_bounds.Inset(-native_window_frame_borders_in_pixels_); - return outer_bounds; -} - -void XWindow::GrabPointer() { - // If the pointer is already in |xwindow_|, we will not get a crossing event - // with a mode of NotifyGrab, so we must record the grab state manually. - has_pointer_grab_ |= - (ui::GrabPointer(xwindow_, true, nullptr) == x11::GrabStatus::Success); -} - -void XWindow::ReleasePointerGrab() { - UngrabPointer(); - has_pointer_grab_ = false; -} - -void XWindow::StackXWindowAbove(x11::Window window) { - DCHECK(window != x11::Window::None); - - // Find all parent windows up to the root. - std::vector window_below_parents = - GetParentsList(connection_, window); - std::vector window_above_parents = - GetParentsList(connection_, xwindow_); - - // Find their common ancestor. - auto it_below_window = window_below_parents.rbegin(); - auto it_above_window = window_above_parents.rbegin(); - for (; it_below_window != window_below_parents.rend() && - it_above_window != window_above_parents.rend() && - *it_below_window == *it_above_window; - ++it_below_window, ++it_above_window) { - } - - if (it_below_window != window_below_parents.rend() && - it_above_window != window_above_parents.rend()) { - connection_->ConfigureWindow(x11::ConfigureWindowRequest{ - .window = *it_above_window, - .sibling = *it_below_window, - .stack_mode = x11::StackMode::Above, - }); - } -} - -void XWindow::StackXWindowAtTop() { - RaiseWindow(xwindow_); -} - -void XWindow::SetCursor(scoped_refptr cursor) { - last_cursor_ = cursor; - on_cursor_loaded_.Reset(base::BindOnce(DefineCursor, xwindow_)); - if (cursor) - cursor->OnCursorLoaded(on_cursor_loaded_.callback()); -} - -bool XWindow::SetTitle(base::string16 title) { - if (window_title_ == title) - return false; - - window_title_ = title; - std::string utf8str = base::UTF16ToUTF8(title); - SetStringProperty(xwindow_, x11::GetAtom("_NET_WM_NAME"), - x11::GetAtom("UTF8_STRING"), utf8str); - SetStringProperty(xwindow_, x11::Atom::WM_NAME, x11::GetAtom("UTF8_STRING"), - utf8str); - return true; -} - -void XWindow::SetXWindowOpacity(float opacity) { - // X server opacity is in terms of 32 bit unsigned int space, and counts from - // the opposite direction. - // XChangeProperty() expects "cardinality" to be long. - - // Scale opacity to [0 .. 255] range. - uint32_t opacity_8bit = static_cast(opacity * 255.0f) & 0xFF; - // Use opacity value for all channels. - uint32_t channel_multiplier = 0x1010101; - uint32_t cardinality = opacity_8bit * channel_multiplier; - - if (cardinality == 0xffffffff) { - x11::DeleteProperty(xwindow_, x11::GetAtom("_NET_WM_WINDOW_OPACITY")); - } else { - SetProperty(xwindow_, x11::GetAtom("_NET_WM_WINDOW_OPACITY"), - x11::Atom::CARDINAL, cardinality); - } -} - -void XWindow::SetXWindowAspectRatio(const gfx::SizeF& aspect_ratio) { - SizeHints size_hints; - memset(&size_hints, 0, sizeof(size_hints)); - - GetWmNormalHints(xwindow_, &size_hints); - // Unforce aspect ratio is parameter length is 0, otherwise set normally. - if (aspect_ratio.IsEmpty()) { - size_hints.flags &= ~SIZE_HINT_P_ASPECT; - } else { - size_hints.flags |= SIZE_HINT_P_ASPECT; - size_hints.min_aspect_num = size_hints.max_aspect_num = - aspect_ratio.width(); - size_hints.min_aspect_den = size_hints.max_aspect_den = - aspect_ratio.height(); - } - SetWmNormalHints(xwindow_, size_hints); -} - -void XWindow::SetXWindowIcons(const gfx::ImageSkia& window_icon, - const gfx::ImageSkia& app_icon) { - // TODO(erg): The way we handle icons across different versions of chrome - // could be substantially improved. The Windows version does its own thing - // and only sometimes comes down this code path. The icon stuff in - // ChromeViewsDelegate is hard coded to use HICONs. Likewise, we're hard - // coded to be given two images instead of an arbitrary collection of images - // so that we can pass to the WM. - // - // All of this could be made much, much better. - std::vector data; - - if (!window_icon.isNull()) - SerializeImageRepresentation(window_icon.GetRepresentation(1.0f), &data); - - if (!app_icon.isNull()) - SerializeImageRepresentation(app_icon.GetRepresentation(1.0f), &data); - - if (!data.empty()) { - SetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_ICON"), - x11::Atom::CARDINAL, data); - } -} - -void XWindow::SetXWindowVisibleOnAllWorkspaces(bool visible) { - SetWMSpecState(visible, x11::GetAtom("_NET_WM_STATE_STICKY"), - x11::Atom::None); - - int new_desktop = 0; - if (visible) { - new_desktop = kAllWorkspaces; - } else { - if (!GetCurrentDesktop(&new_desktop)) - return; - } - - workspace_ = kAllWorkspaces; - SendClientMessage(xwindow_, x_root_window_, x11::GetAtom("_NET_WM_DESKTOP"), - {new_desktop, 0, 0, 0, 0}); -} - -bool XWindow::IsXWindowVisibleOnAllWorkspaces() const { - // We don't need a check for _NET_WM_STATE_STICKY because that would specify - // that the window remain in a fixed position even if the viewport scrolls. - // This is different from the type of workspace that's associated with - // _NET_WM_DESKTOP. - return workspace_ == kAllWorkspaces; -} - -void XWindow::MoveCursorTo(const gfx::Point& location_in_pixels) { - connection_->WarpPointer(x11::WarpPointerRequest{ - .dst_window = x_root_window_, - .dst_x = bounds_in_pixels_.x() + location_in_pixels.x(), - .dst_y = bounds_in_pixels_.y() + location_in_pixels.y(), - }); -} - -void XWindow::ResetWindowRegion() { - std::unique_ptr> xregion; - if (!use_custom_shape() && !IsMaximized() && !IsFullscreen()) { - SkPath window_mask = GetWindowMaskForXWindow(); - // Some frame views define a custom (non-rectangular) window mask. If - // so, use it to define the window shape. If not, fall through. - if (window_mask.countPoints() > 0) - xregion = x11::CreateRegionFromSkPath(window_mask); - } - UpdateWindowRegion(std::move(xregion)); -} - -void XWindow::OnWorkspaceUpdated() { - auto old_workspace = workspace_; - int workspace; - if (GetWindowDesktop(xwindow_, &workspace)) - workspace_ = workspace; - else - workspace_ = base::nullopt; - - if (workspace_ != old_workspace) - OnXWindowWorkspaceChanged(); -} - -void XWindow::SetAlwaysOnTop(bool always_on_top) { - is_always_on_top_ = always_on_top; - SetWMSpecState(always_on_top, x11::GetAtom("_NET_WM_STATE_ABOVE"), - x11::Atom::None); -} - -void XWindow::SetFlashFrameHint(bool flash_frame) { - if (urgency_hint_set_ == flash_frame) - return; - - WmHints hints; - memset(&hints, 0, sizeof(hints)); - GetWmHints(xwindow_, &hints); - - if (flash_frame) - hints.flags |= WM_HINT_X_URGENCY; - else - hints.flags &= ~WM_HINT_X_URGENCY; - - SetWmHints(xwindow_, hints); - - urgency_hint_set_ = flash_frame; -} - -void XWindow::UpdateMinAndMaxSize() { - base::Optional minimum_in_pixels = GetMinimumSizeForXWindow(); - base::Optional 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())) - return; - - min_size_in_pixels_ = minimum_in_pixels.value(); - max_size_in_pixels_ = maximum_in_pixels.value(); - - SizeHints hints; - memset(&hints, 0, sizeof(hints)); - GetWmNormalHints(xwindow_, &hints); - - if (min_size_in_pixels_.IsEmpty()) { - hints.flags &= ~SIZE_HINT_P_MIN_SIZE; - } else { - hints.flags |= SIZE_HINT_P_MIN_SIZE; - hints.min_width = min_size_in_pixels_.width(); - hints.min_height = min_size_in_pixels_.height(); - } - - if (max_size_in_pixels_.IsEmpty()) { - hints.flags &= ~SIZE_HINT_P_MAX_SIZE; - } else { - hints.flags |= SIZE_HINT_P_MAX_SIZE; - hints.max_width = max_size_in_pixels_.width(); - hints.max_height = max_size_in_pixels_.height(); - } - - SetWmNormalHints(xwindow_, hints); -} - -void XWindow::BeforeActivationStateChanged() { - was_active_ = IsActive(); - had_pointer_ = has_pointer_; - had_pointer_grab_ = has_pointer_grab_; - had_window_focus_ = has_window_focus_; -} - -void XWindow::AfterActivationStateChanged() { - if (had_pointer_grab_ && !has_pointer_grab_) - OnXWindowLostPointerGrab(); - - bool had_pointer_capture = had_pointer_ || had_pointer_grab_; - bool has_pointer_capture = has_pointer_ || has_pointer_grab_; - if (had_pointer_capture && !has_pointer_capture) - OnXWindowLostCapture(); - - bool is_active = IsActive(); - if (!was_active_ && is_active) - SetFlashFrameHint(false); - - if (was_active_ != is_active) - OnXWindowIsActiveChanged(is_active); -} - -void XWindow::SetUseNativeFrame(bool use_native_frame) { - use_native_frame_ = use_native_frame; - SetUseOSWindowFrame(xwindow_, use_native_frame); - ResetWindowRegion(); -} - -void XWindow::OnCrossingEvent(bool enter, - bool focus_in_window_or_ancestor, - x11::NotifyMode mode, - x11::NotifyDetail detail) { - // NotifyInferior on a crossing event means the pointer moved into or out of a - // child window, but the pointer is still within |xwindow_|. - if (detail == x11::NotifyDetail::Inferior) - return; - - BeforeActivationStateChanged(); - - if (mode == x11::NotifyMode::Grab) - has_pointer_grab_ = enter; - else if (mode == x11::NotifyMode::Ungrab) - has_pointer_grab_ = false; - - has_pointer_ = enter; - if (focus_in_window_or_ancestor && !has_window_focus_) { - // If we reach this point, we know the focus is in an ancestor or the - // pointer root. The definition of |has_pointer_focus_| is (An ancestor - // window or the PointerRoot is focused) && |has_pointer_|. Therefore, we - // can just use |has_pointer_| in the assignment. The transitions for when - // the focus changes are handled in OnFocusEvent(). - has_pointer_focus_ = has_pointer_; - } - - AfterActivationStateChanged(); -} - -void XWindow::OnFocusEvent(bool focus_in, - x11::NotifyMode mode, - x11::NotifyDetail detail) { - // NotifyInferior on a focus event means the focus moved into or out of a - // child window, but the focus is still within |xwindow_|. - if (detail == x11::NotifyDetail::Inferior) - return; - - bool notify_grab = - mode == x11::NotifyMode::Grab || mode == x11::NotifyMode::Ungrab; - - BeforeActivationStateChanged(); - - // For every focus change, the X server sends normal focus events which are - // useful for tracking |has_window_focus_|, but supplements these events with - // NotifyPointer events which are only useful for tracking pointer focus. - - // For |has_pointer_focus_| and |has_window_focus_|, we continue tracking - // state during a grab, but ignore grab/ungrab events themselves. - if (!notify_grab && detail != x11::NotifyDetail::Pointer) - has_window_focus_ = focus_in; - - if (!notify_grab && has_pointer_) { - switch (detail) { - case x11::NotifyDetail::Ancestor: - case x11::NotifyDetail::Virtual: - // If we reach this point, we know |has_pointer_| was true before and - // after this event. Since the definition of |has_pointer_focus_| is - // (An ancestor window or the PointerRoot is focused) && |has_pointer_|, - // we only need to worry about transitions on the first conjunct. - // Therefore, |has_pointer_focus_| will become true when: - // 1. Focus moves from |xwindow_| to an ancestor - // (FocusOut with NotifyAncestor) - // 2. Focus moves from a descendant of |xwindow_| to an ancestor - // (FocusOut with NotifyVirtual) - // |has_pointer_focus_| will become false when: - // 1. Focus moves from an ancestor to |xwindow_| - // (FocusIn with NotifyAncestor) - // 2. Focus moves from an ancestor to a child of |xwindow_| - // (FocusIn with NotifyVirtual) - has_pointer_focus_ = !focus_in; - break; - case x11::NotifyDetail::Pointer: - // The remaining cases for |has_pointer_focus_| becoming true are: - // 3. Focus moves from |xwindow_| to the PointerRoot - // 4. Focus moves from a descendant of |xwindow_| to the PointerRoot - // 5. Focus moves from None to the PointerRoot - // 6. Focus moves from Other to the PointerRoot - // 7. Focus moves from None to an ancestor of |xwindow_| - // 8. Focus moves from Other to an ancestor of |xwindow_| - // In each case, we will get a FocusIn with a detail of NotifyPointer. - // The remaining cases for |has_pointer_focus_| becoming false are: - // 3. Focus moves from the PointerRoot to |xwindow_| - // 4. Focus moves from the PointerRoot to a descendant of |xwindow| - // 5. Focus moves from the PointerRoot to None - // 6. Focus moves from an ancestor of |xwindow_| to None - // 7. Focus moves from the PointerRoot to Other - // 8. Focus moves from an ancestor of |xwindow_| to Other - // In each case, we will get a FocusOut with a detail of NotifyPointer. - has_pointer_focus_ = focus_in; - break; - case x11::NotifyDetail::Nonlinear: - case x11::NotifyDetail::NonlinearVirtual: - // We get Nonlinear(Virtual) events when - // 1. Focus moves from Other to |xwindow_| - // (FocusIn with NotifyNonlinear) - // 2. Focus moves from Other to a descendant of |xwindow_| - // (FocusIn with NotifyNonlinearVirtual) - // 3. Focus moves from |xwindow_| to Other - // (FocusOut with NotifyNonlinear) - // 4. Focus moves from a descendant of |xwindow_| to Other - // (FocusOut with NotifyNonlinearVirtual) - // |has_pointer_focus_| should be false before and after this event. - has_pointer_focus_ = false; - break; - default: - break; - } - } - - ignore_keyboard_input_ = false; - - AfterActivationStateChanged(); -} - -bool XWindow::IsTargetedBy(const x11::Event& x11_event) const { - return x11_event.window() == xwindow_; -} - -bool XWindow::IsTransientWindowTargetedBy(const x11::Event& x11_event) const { - return x11_event.window() == transient_window_; -} - -void XWindow::SetTransientWindow(x11::Window window) { - transient_window_ = window; -} - -void XWindow::WmMoveResize(int hittest, const gfx::Point& location) const { - int direction = HitTestToWmMoveResizeDirection(hittest); - if (direction == -1) - return; - - DoWMMoveResize(connection_, x_root_window_, xwindow_, location, direction); -} - -void XWindow::OnEvent(const x11::Event& xev) { - // We can lose track of the window's position when the window is reparented. - // When the parent window is moved, we won't get an event, so the window's - // position relative to the root window will get out-of-sync. We can re-sync - // when getting pointer events (EnterNotify, LeaveNotify, ButtonPress, - // ButtonRelease, MotionNotify) which include the pointer location both - // relative to this window and relative to the root window, so we can - // calculate this window's position from that information. - gfx::Point window_point = EventLocationFromXEvent(xev); - gfx::Point root_point = EventSystemLocationFromXEvent(xev); - if (!window_point.IsOrigin() && !root_point.IsOrigin()) { - gfx::Point window_origin = gfx::Point() + (root_point - window_point); - if (bounds_in_pixels_.origin() != window_origin) { - bounds_in_pixels_.set_origin(window_origin); - NotifyBoundsChanged(bounds_in_pixels_); - } - } - - // May want to factor CheckXEventForConsistency(xev); into a common location - // since it is called here. - if (auto* crossing = xev.As()) { - bool focus = crossing->same_screen_focus & CROSSING_FLAG_FOCUS; - OnCrossingEvent(crossing->opcode == x11::CrossingEvent::EnterNotify, focus, - crossing->mode, crossing->detail); - } else if (auto* expose = xev.As()) { - gfx::Rect damage_rect_in_pixels(expose->x, expose->y, expose->width, - expose->height); - OnXWindowDamageEvent(damage_rect_in_pixels); - } else if (auto* focus = xev.As()) { - OnFocusEvent(focus->opcode == x11::FocusEvent::In, focus->mode, - focus->detail); - } else if (auto* configure = xev.As()) { - OnConfigureEvent(*configure); - } else if (auto* crossing = xev.As()) { - TouchFactory* factory = TouchFactory::GetInstance(); - if (factory->ShouldProcessCrossingEvent(*crossing)) { - auto mode = XI2ModeToXMode(crossing->mode); - auto detail = XI2DetailToXDetail(crossing->detail); - switch (crossing->opcode) { - case x11::Input::CrossingEvent::Enter: - OnCrossingEvent(true, crossing->focus, mode, detail); - break; - case x11::Input::CrossingEvent::Leave: - OnCrossingEvent(false, crossing->focus, mode, detail); - break; - case x11::Input::CrossingEvent::FocusIn: - OnFocusEvent(true, mode, detail); - break; - case x11::Input::CrossingEvent::FocusOut: - OnFocusEvent(false, mode, detail); - break; - } - } - } else if (xev.As()) { - OnWindowMapped(); - } else if (xev.As()) { - window_mapped_in_server_ = false; - has_pointer_ = false; - has_pointer_grab_ = false; - has_pointer_focus_ = false; - has_window_focus_ = false; - } else if (auto* client = xev.As()) { - x11::Atom message_type = client->type; - if (message_type == x11::GetAtom("WM_PROTOCOLS")) { - x11::Atom protocol = static_cast(client->data.data32[0]); - if (protocol == x11::GetAtom("WM_DELETE_WINDOW")) { - // We have received a close message from the window manager. - OnXWindowCloseRequested(); - } else if (protocol == x11::GetAtom("_NET_WM_PING")) { - x11::ClientMessageEvent reply_event = *client; - reply_event.window = x_root_window_; - x11::SendEvent(reply_event, x_root_window_, - x11::EventMask::SubstructureNotify | - x11::EventMask::SubstructureRedirect); - } else if (protocol == x11::GetAtom("_NET_WM_SYNC_REQUEST")) { - pending_counter_value_ = - client->data.data32[2] + - (static_cast(client->data.data32[3]) << 32); - pending_counter_value_is_extended_ = client->data.data32[4] != 0; - } - } else { - OnXWindowDragDropEvent(*client); - } - } else if (auto* property = xev.As()) { - x11::Atom changed_atom = property->atom; - if (changed_atom == x11::GetAtom("_NET_WM_STATE")) - OnWMStateUpdated(); - else if (changed_atom == x11::GetAtom("_NET_FRAME_EXTENTS")) - OnFrameExtentsUpdated(); - else if (changed_atom == x11::GetAtom("_NET_WM_DESKTOP")) - OnWorkspaceUpdated(); - } else if (auto* selection = xev.As()) { - OnXWindowSelectionEvent(*selection); - } -} - -void XWindow::UpdateWMUserTime(Event* event) { - if (!IsActive()) - return; - DCHECK(event); - EventType type = event->type(); - if (type == ET_MOUSE_PRESSED || type == ET_KEY_PRESSED || - type == ET_TOUCH_PRESSED) { - uint32_t wm_user_time_ms = - (event->time_stamp() - base::TimeTicks()).InMilliseconds(); - SetProperty(xwindow_, x11::GetAtom("_NET_WM_USER_TIME"), - x11::Atom::CARDINAL, wm_user_time_ms); - } -} - -void XWindow::OnWindowMapped() { - window_mapped_in_server_ = true; - // Some WMs only respect maximize hints after the window has been mapped. - // Check whether we need to re-do a maximization. - if (should_maximize_after_map_) { - Maximize(); - should_maximize_after_map_ = false; - } -} - -void XWindow::OnConfigureEvent(const x11::ConfigureNotifyEvent& configure) { - DCHECK_EQ(xwindow_, configure.window); - DCHECK_EQ(xwindow_, configure.event); - - if (pending_counter_value_) { - DCHECK(!configure_counter_value_); - configure_counter_value_ = pending_counter_value_; - configure_counter_value_is_extended_ = pending_counter_value_is_extended_; - pending_counter_value_is_extended_ = false; - pending_counter_value_ = 0; - } - - // It's possible that the X window may be resized by some other means than - // from within aura (e.g. the X window manager can change the size). Make - // sure the root window size is maintained properly. - int translated_x_in_pixels = configure.x; - int translated_y_in_pixels = configure.y; - if (!configure.send_event && !configure.override_redirect) { - auto future = - connection_->TranslateCoordinates({xwindow_, x_root_window_, 0, 0}); - if (auto coords = future.Sync()) { - translated_x_in_pixels = coords->dst_x; - translated_y_in_pixels = coords->dst_y; - } - } - gfx::Rect bounds_in_pixels(translated_x_in_pixels, translated_y_in_pixels, - configure.width, configure.height); - bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size(); - bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin(); - previous_bounds_in_pixels_ = bounds_in_pixels_; - bounds_in_pixels_ = bounds_in_pixels; - - if (size_changed) - DispatchResize(); - else if (origin_changed) - NotifyBoundsChanged(bounds_in_pixels_); -} - -void XWindow::SetWMSpecState(bool enabled, x11::Atom state1, x11::Atom state2) { - if (window_mapped_in_client_) { - ui::SetWMSpecState(xwindow_, enabled, state1, state2); - } else { - // The updated state will be set when the window is (re)mapped. - base::flat_set new_window_properties = window_properties_; - for (x11::Atom atom : {state1, state2}) { - if (enabled) - new_window_properties.insert(atom); - else - new_window_properties.erase(atom); - } - UpdateWindowProperties(new_window_properties); - } -} - -void XWindow::OnWMStateUpdated() { - // The EWMH spec requires window managers to remove the _NET_WM_STATE property - // when a window is unmapped. However, Chromium code wants the state to - // persist across a Hide() and Show(). So if the window is currently - // unmapped, leave the state unchanged so it will be restored when the window - // is remapped. - std::vector atom_list; - if (GetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_STATE"), &atom_list) || - window_mapped_in_client_) { - UpdateWindowProperties( - base::flat_set(std::begin(atom_list), std::end(atom_list))); - } -} - -void XWindow::UpdateWindowProperties( - const base::flat_set& new_window_properties) { - was_minimized_ = IsMinimized(); - - window_properties_ = new_window_properties; - - // Ignore requests by the window manager to enter or exit fullscreen (e.g. as - // a result of pressing a window manager accelerator key). Chrome does not - // handle window manager initiated fullscreen. In particular, Chrome needs to - // do preprocessing before the x window's fullscreen state is toggled. - - is_always_on_top_ = HasWMSpecProperty(window_properties_, - x11::GetAtom("_NET_WM_STATE_ABOVE")); - OnXWindowStateChanged(); - ResetWindowRegion(); -} - -void XWindow::OnFrameExtentsUpdated() { - std::vector insets; - if (GetArrayProperty(xwindow_, x11::GetAtom("_NET_FRAME_EXTENTS"), &insets) && - insets.size() == 4) { - // |insets| are returned in the order: [left, right, top, bottom]. - native_window_frame_borders_in_pixels_ = - gfx::Insets(insets[2], insets[0], insets[3], insets[1]); - } else { - native_window_frame_borders_in_pixels_ = gfx::Insets(); - } -} - -void XWindow::NotifySwapAfterResize() { - if (configure_counter_value_is_extended_) { - if ((current_counter_value_ % 2) == 1) { - // An increase 3 means that the frame was not drawn as fast as possible. - // This can trigger different handling from the compositor. - // Setting an even number to |extended_update_counter_| will trigger a - // new resize. - current_counter_value_ += 3; - SyncSetCounter(connection_, extended_update_counter_, - current_counter_value_); - } - return; - } - - if (configure_counter_value_ != 0) { - SyncSetCounter(connection_, update_counter_, configure_counter_value_); - configure_counter_value_ = 0; - } -} - -// Removes |delayed_resize_task_| from the task queue (if it's in the queue) and -// adds it back at the end of the queue. -void XWindow::DispatchResize() { - if (update_counter_ == x11::Sync::Counter{} || - configure_counter_value_ == 0) { - // WM doesn't support _NET_WM_SYNC_REQUEST. Or we are too slow, so - // _NET_WM_SYNC_REQUEST is disabled by the compositor. - delayed_resize_task_.Reset(base::BindOnce( - &XWindow::DelayedResize, base::Unretained(this), bounds_in_pixels_)); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, delayed_resize_task_.callback()); - return; - } - - if (configure_counter_value_is_extended_) { - current_counter_value_ = configure_counter_value_; - configure_counter_value_ = 0; - // Make sure the counter is even number. - if ((current_counter_value_ % 2) == 1) - ++current_counter_value_; - } - - // If _NET_WM_SYNC_REQUEST is used to synchronize with compositor during - // resizing, the compositor will not resize the window, until last resize is - // handled, so we don't need accumulate resize events. - DelayedResize(bounds_in_pixels_); -} - -void XWindow::DelayedResize(const gfx::Rect& bounds_in_pixels) { - if (configure_counter_value_is_extended_ && - (current_counter_value_ % 2) == 0) { - // Increase the |extended_update_counter_|, so the compositor will know we - // are not frozen and re-enable _NET_WM_SYNC_REQUEST, if it was disabled. - // Increase the |extended_update_counter_| to an odd number will not trigger - // a new resize. - SyncSetCounter(connection_, extended_update_counter_, - ++current_counter_value_); - } - - CancelResize(); - NotifyBoundsChanged(bounds_in_pixels); - - // No more member accesses here: bounds change propagation may have deleted - // |this| (e.g. when a chrome window is snapped into a tab strip. Further - // details at crbug.com/1068755). -} - -void XWindow::CancelResize() { - delayed_resize_task_.Cancel(); -} - -void XWindow::ConfineCursorTo(const gfx::Rect& bounds) { - UnconfineCursor(); - - if (bounds.IsEmpty()) - return; - - gfx::Rect barrier = bounds + bounds_in_pixels_.OffsetFromOrigin(); - - auto make_barrier = [&](uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, - x11::XFixes::BarrierDirections directions) { - x11::XFixes::Barrier barrier = - connection_->GenerateId(); - connection_->xfixes().CreatePointerBarrier( - {barrier, x_root_window_, x1, y1, x2, y2, directions}); - return barrier; - }; - - // Top horizontal barrier. - pointer_barriers_[0] = - make_barrier(barrier.x(), barrier.y(), barrier.right(), barrier.y(), - x11::XFixes::BarrierDirections::PositiveY); - // Bottom horizontal barrier. - pointer_barriers_[1] = - make_barrier(barrier.x(), barrier.bottom(), barrier.right(), - barrier.bottom(), x11::XFixes::BarrierDirections::NegativeY); - // Left vertical barrier. - pointer_barriers_[2] = - make_barrier(barrier.x(), barrier.y(), barrier.x(), barrier.bottom(), - x11::XFixes::BarrierDirections::PositiveX); - // Right vertical barrier. - pointer_barriers_[3] = - make_barrier(barrier.right(), barrier.y(), barrier.right(), - barrier.bottom(), x11::XFixes::BarrierDirections::NegativeX); - - has_pointer_barriers_ = true; -} - -void XWindow::LowerWindow() { - ui::LowerWindow(xwindow_); -} - -void XWindow::SetOverrideRedirect(bool override_redirect) { - bool remap = window_mapped_in_client_; - if (remap) - Hide(); - connection_->ChangeWindowAttributes(x11::ChangeWindowAttributesRequest{ - .window = xwindow_, - .override_redirect = x11::Bool32(override_redirect), - }); - if (remap) { - Map(); - if (has_pointer_grab_) - ChangeActivePointerGrabCursor(nullptr); - } -} - -bool XWindow::ContainsPointInRegion(const gfx::Point& point) const { - if (!shape()) - return true; - - for (const auto& rect : *shape()) { - if (gfx::Rect(rect.x, rect.y, rect.width, rect.height).Contains(point)) - return true; - } - return false; -} - -void XWindow::SetXWindowShape(std::unique_ptr native_shape, - const gfx::Transform& transform) { - std::unique_ptr> xregion; - if (native_shape) { - SkRegion native_region; - for (const gfx::Rect& rect : *native_shape) - native_region.op(gfx::RectToSkIRect(rect), SkRegion::kUnion_Op); - if (!transform.IsIdentity() && !native_region.isEmpty()) { - SkPath path_in_dip; - if (native_region.getBoundaryPath(&path_in_dip)) { - SkPath path_in_pixels; - path_in_dip.transform(SkMatrix(transform.matrix()), &path_in_pixels); - xregion = x11::CreateRegionFromSkPath(path_in_pixels); - } else { - xregion = std::make_unique>(); - } - } else { - xregion = x11::CreateRegionFromSkRegion(native_region); - } - } - - custom_window_shape_ = !!xregion; - window_shape_ = std::move(xregion); - ResetWindowRegion(); -} - -void XWindow::UnconfineCursor() { - if (!has_pointer_barriers_) - return; - - for (auto pointer_barrier : pointer_barriers_) - connection_->xfixes().DeletePointerBarrier({pointer_barrier}); - - pointer_barriers_.fill({}); - - has_pointer_barriers_ = false; -} - -void XWindow::UpdateWindowRegion( - std::unique_ptr> region) { - auto set_shape = [&](const std::vector& rectangles) { - connection_->shape().Rectangles(x11::Shape::RectanglesRequest{ - .operation = x11::Shape::So::Set, - .destination_kind = x11::Shape::Sk::Bounding, - .ordering = x11::ClipOrdering::YXBanded, - .destination_window = xwindow_, - .rectangles = rectangles, - }); - }; - - // If a custom window shape was supplied then apply it. - if (use_custom_shape()) { - set_shape(*window_shape_); - return; - } - - window_shape_ = std::move(region); - if (window_shape_) { - set_shape(*window_shape_); - return; - } - - // If we didn't set the shape for any reason, reset the shaping information. - // How this is done depends on the border style, due to quirks and bugs in - // various window managers. - if (use_native_frame()) { - // If the window has system borders, the mask must be set to null (not a - // rectangle), because several window managers (eg, KDE, XFCE, XMonad) will - // not put borders on a window with a custom shape. - connection_->shape().Mask(x11::Shape::MaskRequest{ - .operation = x11::Shape::So::Set, - .destination_kind = x11::Shape::Sk::Bounding, - .destination_window = xwindow_, - .source_bitmap = x11::Pixmap::None, - }); - } else { - // Conversely, if the window does not have system borders, the mask must be - // manually set to a rectangle that covers the whole window (not null). This - // is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null - // shape causes the hint to disable system borders to be ignored (resulting - // in a double border). - x11::Rectangle r{0, 0, bounds_in_pixels_.width(), - bounds_in_pixels_.height()}; - set_shape({r}); - } -} - -void XWindow::NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px) { - ResetWindowRegion(); - OnXWindowBoundsChanged(new_bounds_in_px); -} - -bool XWindow::InitializeAsStatusIcon() { - std::string atom_name = "_NET_SYSTEM_TRAY_S" + - base::NumberToString(connection_->DefaultScreenId()); - auto reply = connection_->GetSelectionOwner({x11::GetAtom(atom_name)}).Sync(); - if (!reply || reply->owner == x11::Window::None) - return false; - auto manager = reply->owner; - - SetArrayProperty( - xwindow_, x11::GetAtom("_XEMBED_INFO"), x11::Atom::CARDINAL, - std::vector{kXembedInfoProtocolVersion, kXembedInfoFlags}); - - x11::ChangeWindowAttributesRequest req{xwindow_}; - if (has_alpha()) { - req.background_pixel = 0; - } else { - SetProperty(xwindow_, x11::GetAtom("CHROMIUM_COMPOSITE_WINDOW"), - x11::Atom::CARDINAL, static_cast(1)); - req.background_pixmap = - static_cast(x11::BackPixmap::ParentRelative); - } - connection_->ChangeWindowAttributes(req); - - auto future = SendClientMessage( - manager, manager, x11::GetAtom("_NET_SYSTEM_TRAY_OPCODE"), - {static_cast(X11EventSource::GetInstance()->GetTimestamp()), - kSystemTrayRequestDock, static_cast(xwindow_), 0, 0}, - x11::EventMask::NoEvent); - return !future.Sync().error; -} - -} // namespace ui diff --git a/chromium/ui/base/x/x11_window.h b/chromium/ui/base/x/x11_window.h deleted file mode 100644 index 0a870d41a04..00000000000 --- a/chromium/ui/base/x/x11_window.h +++ /dev/null @@ -1,405 +0,0 @@ -// 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. - -#ifndef UI_BASE_X_X11_WINDOW_H_ -#define UI_BASE_X_X11_WINDOW_H_ - -#include -#include -#include -#include - -#include "base/cancelable_callback.h" -#include "base/component_export.h" -#include "base/containers/flat_set.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/strings/string16.h" -#include "ui/base/x/x11_cursor.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/geometry/size_f.h" -#include "ui/gfx/x/event.h" -#include "ui/gfx/x/sync.h" -#include "ui/gfx/x/xfixes.h" -#include "ui/gfx/x/xproto.h" - -class SkPath; - -namespace gfx { -class ImageSkia; -class Transform; -} // namespace gfx - -namespace x11 { -class XScopedEventSelector; -} - -namespace ui { - -class Event; -class X11Cursor; - -//////////////////////////////////////////////////////////////////////////////// -// XWindow class -// -// Base class that encapsulates a full featured Xlib-based X11 Window, meant -// to be used mainly in Linux desktop. Abstracts away most of X11 API -// interaction and assumes event handling and some required getters are -// implemented in subclasses. -// -// |XWindow::Configuration| holds parameters used in window initialization. -// Fields are equivalent and a sub-set of Widget::InitParams. -// -// All bounds and size values are assumed to be expressed in pixels. -class COMPONENT_EXPORT(UI_BASE_X) XWindow { - public: - using NativeShapeRects = std::vector; - - enum class WindowType { - kWindow, - kPopup, - kMenu, - kTooltip, - kDrag, - kBubble, - }; - - enum class WindowOpacity { - kInferOpacity, - kOpaqueWindow, - kTranslucentWindow, - }; - - struct Configuration final { - Configuration(); - Configuration(const Configuration& config); - ~Configuration(); - - WindowType type; - WindowOpacity opacity; - gfx::Rect bounds; - gfx::ImageSkia* icon; - base::Optional background_color; - bool activatable; - bool force_show_in_taskbar; - bool keep_on_top; - bool visible_on_all_workspaces; - bool remove_standard_frame; - bool prefer_dark_theme; - bool override_redirect; - std::string workspace; - std::string wm_class_name; - std::string wm_class_class; - std::string wm_role_name; - }; - - XWindow(); - XWindow(const XWindow&) = delete; - XWindow& operator=(const XWindow&) = delete; - virtual ~XWindow(); - - void Init(const Configuration& config); - void Map(bool inactive = false); - void Close(); - void Maximize(); - void Minimize(); - void Unmaximize(); - bool Hide(); - void Unhide(); - void SetFullscreen(bool fullscreen); - void Activate(); - void Deactivate(); - bool IsActive() const; - void GrabPointer(); - void ReleasePointerGrab(); - void StackXWindowAbove(x11::Window window); - void StackXWindowAtTop(); - bool IsTargetedBy(const x11::Event& xev) const; - bool IsTransientWindowTargetedBy(const x11::Event& x11_event) const; - void SetTransientWindow(x11::Window window); - void WmMoveResize(int hittest, const gfx::Point& location) const; - void OnEvent(const x11::Event& xev); - - void SetSize(const gfx::Size& size_in_pixels); - void SetBounds(const gfx::Rect& requested_bounds); - bool IsXWindowVisible() const; - bool IsMinimized() const; - bool IsMaximized() const; - bool IsFullscreen() const; - gfx::Rect GetOuterBounds() const; - - void SetCursor(scoped_refptr cursor); - bool SetTitle(base::string16 title); - void SetXWindowOpacity(float opacity); - void SetXWindowAspectRatio(const gfx::SizeF& aspect_ratio); - void SetXWindowIcons(const gfx::ImageSkia& window_icon, - const gfx::ImageSkia& app_icon); - void SetXWindowVisibleOnAllWorkspaces(bool visible); - bool IsXWindowVisibleOnAllWorkspaces() const; - void MoveCursorTo(const gfx::Point& location); - void SetAlwaysOnTop(bool always_on_top); - void SetFlashFrameHint(bool flash_frame); - void UpdateMinAndMaxSize(); - void SetUseNativeFrame(bool use_native_frame); - void DispatchResize(); - void CancelResize(); - void NotifySwapAfterResize(); - void ConfineCursorTo(const gfx::Rect& bounds); - void LowerWindow(); - void SetOverrideRedirect(bool override_redirect); - - // Returns if the point is within XWindow shape. If shape is not set, always - // returns true. - bool ContainsPointInRegion(const gfx::Point& point) const; - - void SetXWindowShape(std::unique_ptr native_shape, - const gfx::Transform& transform); - - // Resets the window region for the current window bounds if necessary. - void ResetWindowRegion(); - - gfx::Rect bounds() const { return bounds_in_pixels_; } - gfx::Rect previous_bounds() const { return previous_bounds_in_pixels_; } - void set_bounds(gfx::Rect new_bounds) { bounds_in_pixels_ = new_bounds; } - - bool mapped_in_client() const { return window_mapped_in_client_; } - bool is_always_on_top() const { return is_always_on_top_; } - bool use_native_frame() const { return use_native_frame_; } - bool use_custom_shape() const { return custom_window_shape_; } - bool was_minimized() const { return was_minimized_; } - bool has_alpha() const { return visual_has_alpha_; } - base::Optional workspace() const { return workspace_; } - - x11::Connection* connection() const { return connection_; } - x11::Window window() const { return xwindow_; } - x11::Window root_window() const { return x_root_window_; } - std::vector* shape() const { return window_shape_.get(); } - x11::Sync::Counter update_counter() const { return update_counter_; } - x11::Sync::Counter extended_update_counter() const { - return extended_update_counter_; - } - scoped_refptr last_cursor() const { return last_cursor_; } - - protected: - // Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active. - void UpdateWMUserTime(ui::Event* event); - - private: - // Called on an XFocusInEvent, XFocusOutEvent, XIFocusInEvent, or an - // XIFocusOutEvent. - void OnFocusEvent(bool focus_in, - x11::NotifyMode mode, - x11::NotifyDetail detail); - - // Called on an XEnterWindowEvent, XLeaveWindowEvent, XIEnterEvent, or an - // XILeaveEvent. - void OnCrossingEvent(bool enter, - bool focus_in_window_or_ancestor, - x11::NotifyMode mode, - x11::NotifyDetail detail); - - // Called when |xwindow_|'s _NET_WM_STATE property is updated. - void OnWMStateUpdated(); - - // Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated. - void OnFrameExtentsUpdated(); - - void OnConfigureEvent(const x11::ConfigureNotifyEvent& event); - - void OnWorkspaceUpdated(); - - void OnWindowMapped(); - - // Record the activation state. - void BeforeActivationStateChanged(); - - // Handle the state change since BeforeActivationStateChanged(). - void AfterActivationStateChanged(); - - void DelayedResize(const gfx::Rect& bounds_in_pixels); - - // If mapped, sends a message to the window manager to enable or disable the - // states |state1| and |state2|. Otherwise, the states will be enabled or - // disabled on the next map. It's the caller's responsibility to make sure - // atoms are set and unset in the appropriate pairs. For example, if a caller - // sets (_NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ), it would - // be invalid to unset the maximized state by making two calls like - // (_NET_WM_STATE_MAXIMIZED_VERT, x11::None), (_NET_WM_STATE_MAXIMIZED_HORZ, - // x11::None). - void SetWMSpecState(bool enabled, x11::Atom state1, x11::Atom state2); - - // Updates |window_properties_| with |new_window_properties|. - void UpdateWindowProperties( - const base::flat_set& new_window_properties); - - void UnconfineCursor(); - - void UpdateWindowRegion(std::unique_ptr> region); - - void NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px); - - // Initializes as a status icon window. - bool InitializeAsStatusIcon(); - - // Interface that must be used by a class that inherits the XWindow to receive - // different messages from X Server. - virtual void OnXWindowCreated() = 0; - virtual void OnXWindowStateChanged() = 0; - virtual void OnXWindowDamageEvent(const gfx::Rect& damage_rect) = 0; - virtual void OnXWindowBoundsChanged(const gfx::Rect& size) = 0; - virtual void OnXWindowCloseRequested() = 0; - virtual void OnXWindowIsActiveChanged(bool active) = 0; - virtual void OnXWindowWorkspaceChanged() = 0; - virtual void OnXWindowLostPointerGrab() = 0; - virtual void OnXWindowLostCapture() = 0; - virtual void OnXWindowSelectionEvent( - const x11::SelectionNotifyEvent& xev) = 0; - virtual void OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev) = 0; - virtual base::Optional GetMinimumSizeForXWindow() = 0; - virtual base::Optional GetMaximumSizeForXWindow() = 0; - virtual SkPath GetWindowMaskForXWindow() = 0; - - // The display and the native X window hosting the root window. - x11::Connection* const connection_; - x11::Window xwindow_ = x11::Window::None; - x11::Window x_root_window_ = x11::Window::None; - - // Any native, modal dialog hanging from this window. - x11::Window transient_window_ = x11::Window::None; - - // Events selected on |xwindow_|. - std::unique_ptr xwindow_events_; - - // The window manager state bits. - base::flat_set window_properties_; - - // Is this window able to receive focus? - bool activatable_ = true; - - // Was this window initialized with the override_redirect window attribute? - bool override_redirect_ = false; - - base::string16 window_title_; - - // Whether the window is visible with respect to Aura. - bool window_mapped_in_client_ = false; - - // Whether the window is mapped with respect to the X server. - bool window_mapped_in_server_ = false; - - // The bounds of |xwindow_|. - gfx::Rect bounds_in_pixels_; - - x11::VisualId visual_id_{}; - - // Whether we used an ARGB visual for our window. - bool visual_has_alpha_ = false; - - // The workspace containing |xwindow_|. This will be base::nullopt when - // _NET_WM_DESKTOP is unset. - base::Optional workspace_; - - // True if the window should stay on top of most other windows. - bool is_always_on_top_ = false; - - // Does |xwindow_| have the pointer grab (XI2 or normal)? - bool has_pointer_grab_ = false; - - // The focus-tracking state variables are as described in - // gtk/docs/focus_tracking.txt - // - // |xwindow_| is active iff: - // (|has_window_focus_| || |has_pointer_focus_|) && - // !|ignore_keyboard_input_| - - // Is the pointer in |xwindow_| or one of its children? - bool has_pointer_ = false; - - // Is |xwindow_| or one of its children focused? - bool has_window_focus_ = false; - - // (An ancestor window or the PointerRoot is focused) && |has_pointer_|. - // |has_pointer_focus_| == true is the odd case where we will receive keyboard - // input when |has_window_focus_| == false. |has_window_focus_| and - // |has_pointer_focus_| are mutually exclusive. - bool has_pointer_focus_ = false; - - // X11 does not support defocusing windows; you can only focus a different - // window. If we would like to be defocused, we just ignore keyboard input we - // no longer care about. - bool ignore_keyboard_input_ = false; - - // Used for tracking activation state in {Before|After}ActivationStateChanged. - bool was_active_ = false; - bool had_pointer_ = false; - bool had_pointer_grab_ = false; - bool had_window_focus_ = false; - - bool was_minimized_ = false; - - // Used for synchronizing between |xwindow_| and desktop compositor during - // resizing. - x11::Sync::Counter update_counter_{}; - x11::Sync::Counter extended_update_counter_{}; - - // Whenever the bounds are set, we keep the previous set of bounds around so - // we can have a better chance of getting the real - // |restored_bounds_in_pixels_|. Window managers tend to send a Configure - // message with the maximized bounds, and then set the window maximized - // property. (We don't rely on this for when we request that the window be - // maximized, only when we detect that some other process has requested that - // we become the maximized window.) - gfx::Rect previous_bounds_in_pixels_; - - // True if a Maximize() call should be done after mapping the window. - bool should_maximize_after_map_ = false; - - // Whether we currently are flashing our frame. This feature is implemented - // by setting the urgency hint with the window manager, which can draw - // attention to the window or completely ignore the hint. We stop flashing - // the frame when |xwindow_| gains focus or handles a mouse button event. - bool urgency_hint_set_ = false; - - // |xwindow_|'s minimum size. - gfx::Size min_size_in_pixels_; - - // |xwindow_|'s maximum size. - gfx::Size max_size_in_pixels_; - - // The window shape if the window is non-rectangular. - std::unique_ptr> window_shape_; - - // Whether |window_shape_| was set via SetShape(). - bool custom_window_shape_ = false; - - // True if the window has title-bar / borders provided by the window manager. - bool use_native_frame_ = false; - - // The size of the window manager provided borders (if any). - gfx::Insets native_window_frame_borders_in_pixels_; - - // Used for synchronizing between |xwindow_| between desktop compositor during - // resizing. - int64_t pending_counter_value_ = 0; - int64_t configure_counter_value_ = 0; - int64_t current_counter_value_ = 0; - bool pending_counter_value_is_extended_ = false; - bool configure_counter_value_is_extended_ = false; - - base::CancelableOnceClosure delayed_resize_task_; - - // Keep track of barriers to confine cursor. - bool has_pointer_barriers_ = false; - std::array pointer_barriers_; - - scoped_refptr last_cursor_; - - base::CancelableOnceCallback on_cursor_loaded_; -}; - -} // namespace ui - -#endif // UI_BASE_X_X11_WINDOW_H_ diff --git a/chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.cc b/chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.cc new file mode 100644 index 00000000000..03e4f765596 --- /dev/null +++ b/chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.cc @@ -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. + +#include "ui/base/x/x11_xrandr_interval_only_vsync_provider.h" + +#include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" +#include "ui/base/x/x11_display_util.h" + +namespace ui { + +XrandrIntervalOnlyVSyncProvider::XrandrIntervalOnlyVSyncProvider() + : interval_(base::TimeDelta::FromSeconds(1 / 60.)) {} + +void XrandrIntervalOnlyVSyncProvider::GetVSyncParameters( + UpdateVSyncCallback callback) { + if (++calls_since_last_update_ >= kCallsBetweenUpdates) { + calls_since_last_update_ = 0; + interval_ = GetPrimaryDisplayRefreshIntervalFromXrandr(); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), base::TimeTicks(), interval_)); +} + +bool XrandrIntervalOnlyVSyncProvider::GetVSyncParametersIfAvailable( + base::TimeTicks* timebase, + base::TimeDelta* interval) { + return false; +} + +bool XrandrIntervalOnlyVSyncProvider::SupportGetVSyncParametersIfAvailable() + const { + return false; +} + +bool XrandrIntervalOnlyVSyncProvider::IsHWClock() const { + return false; +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.h b/chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.h new file mode 100644 index 00000000000..c528c8f78b1 --- /dev/null +++ b/chromium/ui/base/x/x11_xrandr_interval_only_vsync_provider.h @@ -0,0 +1,34 @@ +// 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_XRANDR_INTERVAL_ONLY_VSYNC_PROVIDER_H_ +#define UI_BASE_X_X11_XRANDR_INTERVAL_ONLY_VSYNC_PROVIDER_H_ + +#include "base/component_export.h" +#include "base/time/time.h" +#include "ui/gfx/vsync_provider.h" + +namespace ui { + +class COMPONENT_EXPORT(UI_BASE_X) XrandrIntervalOnlyVSyncProvider + : public gfx::VSyncProvider { + public: + explicit XrandrIntervalOnlyVSyncProvider(); + + // gfx::VSyncProvider: + void GetVSyncParameters(UpdateVSyncCallback callback) override; + bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase, + base::TimeDelta* interval) override; + bool SupportGetVSyncParametersIfAvailable() const override; + bool IsHWClock() const override; + + private: + base::TimeDelta interval_; + static const int kCallsBetweenUpdates = 100; + int calls_since_last_update_ = kCallsBetweenUpdates; +}; + +} // namespace ui + +#endif // UI_BASE_X_X11_XRANDR_INTERVAL_ONLY_VSYNC_PROVIDER_H_ diff --git a/chromium/ui/chromeos/strings/BUILD.gn b/chromium/ui/chromeos/strings/BUILD.gn index f41128adf85..27ed84e7ddb 100644 --- a/chromium/ui/chromeos/strings/BUILD.gn +++ b/chromium/ui/chromeos/strings/BUILD.gn @@ -9,6 +9,6 @@ grit("strings") { source = "../ui_chromeos_strings.grd" outputs = [ "grit/ui_chromeos_strings.h" ] + - process_file_template(locales_with_fake_bidi, + process_file_template(locales_with_pseudolocales, [ "ui_chromeos_strings_{{source_name_part}}.pak" ]) } diff --git a/chromium/ui/color/BUILD.gn b/chromium/ui/color/BUILD.gn index ca2c15eaa1d..b0c1eba7fed 100644 --- a/chromium/ui/color/BUILD.gn +++ b/chromium/ui/color/BUILD.gn @@ -13,6 +13,8 @@ source_set("color_headers") { "color_id_macros.inc", "color_mixer.h", "color_provider.h", + "color_provider_manager.h", + "color_provider_utils.h", "color_set.h", ] @@ -26,8 +28,8 @@ component("color") { sources = [ "color_mixer.cc", "color_provider.cc", - "color_provider_manager.cc", - "color_provider_manager.h", + "color_provider_utils.cc", + "color_provider_utils.h", "color_recipe.cc", "color_recipe.h", "color_set.cc", @@ -43,6 +45,15 @@ component("color") { "//skia:skia", "//ui/gfx:color_utils", ] + + if (is_mac) { + frameworks = [ "AppKit.framework" ] + sources += [ + "mac/native_color_transform.mm", + "mac/system_color_utils.h", + "mac/system_color_utils.mm", + ] + } } test("color_unittests") { @@ -60,6 +71,7 @@ test("color_unittests") { deps = [ ":color", + ":mixers", "//base/test:test_support", "//testing/gtest", ] @@ -68,6 +80,8 @@ test("color_unittests") { component("mixers") { sources = [ "color_mixers.h", + "color_provider_manager.cc", + "color_provider_manager.h", "core_default_color_mixer.cc", "ui_color_mixer.cc", ] @@ -96,6 +110,8 @@ component("mixers") { "mac/scoped_current_nsappearance.h", "mac/scoped_current_nsappearance.mm", ] + } else if (is_ios) { + sources += [ "ios/native_color_mixers.mm" ] } else if (is_win) { sources += [ "win/native_color_mixers.cc" ] } diff --git a/chromium/ui/color/OWNERS b/chromium/ui/color/OWNERS index bf426d601e0..2926b03102b 100644 --- a/chromium/ui/color/OWNERS +++ b/chromium/ui/color/OWNERS @@ -1 +1,2 @@ pkasting@chromium.org +tluk@chromium.org diff --git a/chromium/ui/color/color_id.h b/chromium/ui/color/color_id.h index f050e8164bf..748c21d1496 100644 --- a/chromium/ui/color/color_id.h +++ b/chromium/ui/color/color_id.h @@ -12,26 +12,35 @@ // clang-format off #define CROSS_PLATFORM_COLOR_IDS \ /* Core color concepts */ \ - E_CPONLY(kColorAccent, kUiColorsStart) \ + /* Use the 3 param macro so kColorAccent is set to the correct value. */ \ + E_CPONLY(kColorAccent, kUiColorsStart, kUiColorsStart) \ E(kColorAlertHighSeverity, NativeTheme::kColorId_AlertSeverityHigh) \ E(kColorAlertLowSeverity, NativeTheme::kColorId_AlertSeverityLow) \ E(kColorAlertMediumSeverity, NativeTheme::kColorId_AlertSeverityMedium) \ E_CPONLY(kColorDisabledForeground) \ + E_CPONLY(kColorEndpointBackground) \ + E_CPONLY(kColorEndpointForeground) \ + E_CPONLY(kColorItemHighlight) \ E_CPONLY(kColorItemSelectionBackground) \ + E_CPONLY(kColorMenuSelectionBackground) \ E_CPONLY(kColorMidground) \ E_CPONLY(kColorPrimaryBackground) \ E_CPONLY(kColorPrimaryForeground) \ E_CPONLY(kColorSecondaryForeground) \ + E_CPONLY(kColorSubtleAccent) \ E_CPONLY(kColorSubtleEmphasisBackground) \ E_CPONLY(kColorTextSelectionBackground) \ + E_CPONLY(kColorTextSelectionForeground) \ \ /* Further UI element colors */ \ E(kColorAvatarHeaderArt, NativeTheme::kColorId_AvatarHeaderArt) \ E(kColorAvatarIconGuest, NativeTheme::kColorId_AvatarIconGuest) \ E(kColorAvatarIconIncognito, NativeTheme::kColorId_AvatarIconIncognito) \ E(kColorBubbleBackground, NativeTheme::kColorId_BubbleBackground) \ + E(kColorBubbleBorder, NativeTheme::kColorId_BubbleBorder) \ E(kColorBubbleFooterBackground, \ NativeTheme::kColorId_BubbleFooterBackground) \ + E(kColorBubbleFooterBorder, NativeTheme::kColorId_BubbleFooterBorder) \ E(kColorButtonBackground, NativeTheme::kColorId_ButtonColor) \ /* TODO(https://crbug.com/1003612): Map this to old color id. */ \ E_CPONLY(kColorButtonBackgroundPressed) \ @@ -45,6 +54,7 @@ E(kColorButtonBorderDisabled, \ NativeTheme::kColorId_DisabledButtonBorderColor) \ E(kColorButtonForeground, NativeTheme::kColorId_ButtonEnabledColor) \ + E(kColorButtonForegroundChecked, NativeTheme::kColorId_ButtonCheckedColor) \ E(kColorButtonForegroundDisabled, NativeTheme::kColorId_ButtonDisabledColor) \ E(kColorButtonForegroundProminent, \ NativeTheme::kColorId_TextOnProminentButtonColor) \ @@ -52,10 +62,21 @@ NativeTheme::kColorId_ButtonUncheckedColor) \ E(kColorDialogBackground, NativeTheme::kColorId_DialogBackground) \ E(kColorDialogForeground, NativeTheme::kColorId_DialogForeground) \ + E(kColorDropdownBackground, NativeTheme::kColorId_DropdownBackgroundColor) \ + E(kColorDropdownBackgroundSelected, \ + NativeTheme::kColorId_DropdownSelectedBackgroundColor) \ + E(kColorDropdownForeground, NativeTheme::kColorId_DropdownForegroundColor) \ + E(kColorDropdownForegroundSelected, \ + NativeTheme::kColorId_DropdownSelectedForegroundColor) \ E(kColorFocusableBorderFocused, NativeTheme::kColorId_FocusedBorderColor) \ E(kColorFocusableBorderUnfocused, \ NativeTheme::kColorId_UnfocusedBorderColor) \ + 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(kColorLabelForeground, NativeTheme::kColorId_LabelEnabledColor) \ E(kColorLabelForegroundDisabled, NativeTheme::kColorId_LabelDisabledColor) \ E(kColorLabelForegroundSecondary, NativeTheme::kColorId_LabelSecondaryColor) \ @@ -68,6 +89,7 @@ E(kColorLinkForegroundPressed, NativeTheme::kColorId_LinkPressed) \ E(kColorMenuBackground, NativeTheme::kColorId_MenuBackgroundColor) \ E(kColorMenuBorder, NativeTheme::kColorId_MenuBorderColor) \ + E(kColorMenuDropmarker, NativeTheme::kColorId_MenuDropIndicator) \ E(kColorMenuIcon, NativeTheme::kColorId_MenuIconColor) \ E(kColorMenuItemBackgroundAlertedInitial, \ NativeTheme::kColorId_MenuItemInitialAlertBackgroundColor) \ @@ -88,12 +110,69 @@ E(kColorMenuItemForegroundSelected, \ NativeTheme::kColorId_SelectedMenuItemForegroundColor) \ E(kColorMenuSeparator, NativeTheme::kColorId_MenuSeparatorColor) \ + E(kColorNotificationActionsBackground, \ + NativeTheme::kColorId_NotificationActionsRowBackground) \ + E(kColorNotificationBackgroundActive, \ + NativeTheme::kColorId_NotificationBackgroundActive) \ + E(kColorNotificationBackgroundInactive, \ + NativeTheme::kColorId_NotificationBackground) \ + E(kColorNotificationHeaderForeground, \ + NativeTheme::kColorId_NotificationDefaultAccentColor) \ + E(kColorNotificationIconBackground, \ + NativeTheme::kColorId_MessageCenterSmallImageMaskBackground) \ + E(kColorNotificationIconForeground, \ + NativeTheme::kColorId_MessageCenterSmallImageMaskForeground) \ + E(kColorNotificationImageBackground, \ + NativeTheme::kColorId_NotificationLargeImageBackground) \ + E(kColorNotificationInputBackground, \ + NativeTheme::kColorId_NotificationInkDropBase) \ + E(kColorNotificationInputForeground, \ + NativeTheme::kColorId_NotificationColor) \ + E(kColorNotificationInputPlaceholderForeground, \ + NativeTheme::kColorId_NotificationPlaceholderColor) \ + E(kColorOverlayScrollbarFill, \ + NativeTheme::kColorId_OverlayScrollbarThumbFill) \ + E(kColorOverlayScrollbarFillHovered, \ + NativeTheme::kColorId_OverlayScrollbarThumbHoveredFill) \ + E(kColorOverlayScrollbarStroke, \ + NativeTheme::kColorId_OverlayScrollbarThumbStroke) \ + E(kColorOverlayScrollbarStrokeHovered, \ + NativeTheme::kColorId_OverlayScrollbarThumbHoveredStroke) \ + E(kColorPwaSecurityChipForeground, \ + NativeTheme::kColorId_CustomTabBarSecurityChipDefaultColor) \ + E(kColorPwaSecurityChipForegroundDangerous, \ + NativeTheme::kColorId_CustomTabBarSecurityChipDangerousColor) \ + E(kColorPwaSecurityChipForegroundPolicyCert, \ + NativeTheme::kColorId_CustomTabBarSecurityChipWithCertColor) \ + E(kColorPwaSecurityChipForegroundSecure, \ + NativeTheme::kColorId_CustomTabBarSecurityChipSecureColor) \ + E(kColorPwaToolbarBackground, \ + NativeTheme::kColorId_CustomTabBarBackgroundColor) \ + E(kColorPwaToolbarForeground, \ + NativeTheme::kColorId_CustomTabBarForegroundColor) \ + E(kColorSeparator, NativeTheme::kColorId_SeparatorColor) \ + E(kColorSliderThumb, NativeTheme::kColorId_SliderThumbDefault) \ + E(kColorSliderThumbMinimal, NativeTheme::kColorId_SliderThumbMinimal) \ + E(kColorSliderTrack, NativeTheme::kColorId_SliderTroughDefault) \ + E(kColorSliderTrackMinimal, NativeTheme::kColorId_SliderTroughMinimal) \ + E(kColorSyncInfoBackground, \ + NativeTheme::kColorId_SyncInfoContainerNoPrimaryAccount) \ + E(kColorSyncInfoBackgroundError, \ + NativeTheme::kColorId_SyncInfoContainerError) \ + E(kColorSyncInfoBackgroundPaused, \ + NativeTheme::kColorId_SyncInfoContainerPaused) \ + E(kColorTabBackgroundHighlighted, \ + NativeTheme::kColorId_TabHighlightBackground) \ + E(kColorTabBackgroundHighlightedFocused, \ + NativeTheme::kColorId_TabHighlightFocusedBackground) \ E(kColorTabBorderSelected, NativeTheme::kColorId_TabSelectedBorderColor) \ E(kColorTabContentSeparator, NativeTheme::kColorId_TabBottomBorder) \ E(kColorTabForeground, NativeTheme::kColorId_TabTitleColorInactive) \ E(kColorTabForegroundSelected, \ NativeTheme::kColorId_TabTitleColorActive) \ E(kColorTableBackground, NativeTheme::kColorId_TableBackground) \ + E(kColorTableBackgroundAlternate, \ + NativeTheme::kColorId_TableBackgroundAlternate) \ E(kColorTableBackgroundSelectedFocused, \ NativeTheme::kColorId_TableSelectionBackgroundFocused) \ E(kColorTableBackgroundSelectedUnfocused, \ @@ -122,6 +201,14 @@ E(kColorTextfieldSelectionForeground, \ NativeTheme::kColorId_TextfieldSelectionColor) \ E(kColorThrobber, NativeTheme::kColorId_ThrobberSpinningColor) \ + E(kColorThrobberPreconnect, NativeTheme::kColorId_ThrobberWaitingColor) \ + E(kColorToggleButtonShadow, NativeTheme::kColorId_ToggleButtonShadowColor) \ + E(kColorToggleButtonThumbOff, \ + NativeTheme::kColorId_ToggleButtonThumbColorOff) \ + E(kColorToggleButtonThumbOn, NativeTheme::kColorId_ToggleButtonThumbColorOn) \ + E(kColorToggleButtonTrackOff, \ + NativeTheme::kColorId_ToggleButtonTrackColorOff) \ + E(kColorToggleButtonTrackOn, NativeTheme::kColorId_ToggleButtonTrackColorOn) \ E(kColorTooltipBackground, NativeTheme::kColorId_TooltipBackground) \ E(kColorTooltipForeground, NativeTheme::kColorId_TooltipText) \ E(kColorTreeBackground, NativeTheme::kColorId_TreeBackground) \ @@ -171,20 +258,10 @@ E(kColorNativeWindowText, COLOR_WINDOWTEXT) #endif -#if defined(OS_APPLE) -#define MACOSX_COLOR_IDS \ - E(kColorTableBackgroundAlternate, \ - NativeTheme::kColorId_TableBackgroundAlternate) -#endif - #if defined(OS_WIN) #define COLOR_IDS \ CROSS_PLATFORM_COLOR_IDS \ WIN_COLOR_IDS -#elif defined(OS_APPLE) -#define COLOR_IDS \ - CROSS_PLATFORM_COLOR_IDS \ - MACOSX_COLOR_IDS #else #define COLOR_IDS CROSS_PLATFORM_COLOR_IDS #endif diff --git a/chromium/ui/color/color_mixer.cc b/chromium/ui/color/color_mixer.cc index 2069d5b0fb1..e0a2b05664f 100644 --- a/chromium/ui/color/color_mixer.cc +++ b/chromium/ui/color/color_mixer.cc @@ -4,13 +4,17 @@ #include "ui/color/color_mixer.h" +#include "base/logging.h" +#include "ui/color/color_provider_utils.h" #include "ui/color/color_recipe.h" #include "ui/gfx/color_palette.h" namespace ui { -ColorMixer::ColorMixer(const ColorMixer* previous_mixer) - : previous_mixer_(previous_mixer) {} +ColorMixer::ColorMixer(const ColorMixer* previous_mixer, + MixerGetter input_mixer_getter) + : previous_mixer_(previous_mixer), + input_mixer_getter_(std::move(input_mixer_getter)) {} ColorMixer::ColorMixer(ColorMixer&&) noexcept = default; @@ -25,6 +29,7 @@ ColorRecipe& ColorMixer::operator[](ColorId id) { void ColorMixer::AddSet(ColorSet&& set) { DCHECK(FindSetWithId(set.id) == sets_.cend()); + DVLOG(2) << "ColorSet " << ColorSetIdName(set.id) << " added."; sets_.push_front(std::move(set)); } @@ -32,9 +37,22 @@ SkColor ColorMixer::GetInputColor(ColorId id) const { DCHECK_COLOR_ID_VALID(id); for (const auto& set : sets_) { const auto i = set.colors.find(id); - if (i != set.colors.end()) + if (i != set.colors.end()) { + DVLOG(2) << "GetInputColor: ColorId " << ColorIdName(id) + << " found within ColorSet " << ColorSetIdName(set.id) + << " Result Color: " << SkColorName(i->second) << "."; return i->second; + } } + // Don't log transitions to previous mixers unless the logging level is a + // little higher. + DVLOG_IF(3, previous_mixer_) + << "GetInputColor: ColorId " << ColorIdName(id) << " not found. " + << "Checking previous mixer."; + // If there's no previous mixer, always log color id misses. + DVLOG_IF(2, !previous_mixer_) + << "GetInputColor: ColorId " << ColorIdName(id) << " not found. " + << "Returning gfx::kPlaceholderColor."; return previous_mixer_ ? previous_mixer_->GetResultColor(id) : gfx::kPlaceholderColor; } @@ -46,9 +64,22 @@ SkColor ColorMixer::GetOriginalColorFromSet(ColorId id, const auto i = FindSetWithId(set_id); if (i != sets_.end()) { const auto j = i->colors.find(id); - if (j != i->colors.end()) + if (j != i->colors.end()) { + DVLOG(2) << "GetOriginalColorFromSet: ColorId " << ColorIdName(id) + << " found within ColorSet " << ColorSetIdName(i->id) + << " Result Color: " << SkColorName(j->second) << "."; return j->second; + } } + // Don't log transitions to previous mixers unless the logging level is a + // little higher. + DVLOG_IF(3, previous_mixer_) + << "GetOriginalColorFromSet: ColorId " << ColorIdName(id) + << " not found. Checking previous mixer."; + // If there's no previous mixer, always log color id misses. + DVLOG_IF(2, !previous_mixer_) + << "GetOriginalColorFromSet: ColorId " << ColorIdName(id) + << " not found. Returning gfx::kPlaceholderColor."; return previous_mixer_ ? previous_mixer_->GetOriginalColorFromSet(id, set_id) : gfx::kPlaceholderColor; } @@ -57,7 +88,11 @@ SkColor ColorMixer::GetResultColor(ColorId id) const { DCHECK_COLOR_ID_VALID(id); const SkColor color = GetInputColor(id); const auto i = recipes_.find(id); - return (i == recipes_.end()) ? color : i->second.GenerateResult(color, *this); + const ColorMixer* const mixer = + input_mixer_getter_ ? input_mixer_getter_.Run() : nullptr; + return (i == recipes_.end()) + ? color + : i->second.GenerateResult(color, *(mixer ? mixer : this)); } ColorMixer::ColorSets::const_iterator ColorMixer::FindSetWithId( diff --git a/chromium/ui/color/color_mixer.h b/chromium/ui/color/color_mixer.h index 899f894f59e..c2215bd39b0 100644 --- a/chromium/ui/color/color_mixer.h +++ b/chromium/ui/color/color_mixer.h @@ -8,6 +8,8 @@ #include #include +#include "base/callback_forward.h" +#include "base/callback_helpers.h" #include "base/component_export.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/color/color_id.h" @@ -28,11 +30,16 @@ class ColorRecipe; // mixers in the pipeline. class COMPONENT_EXPORT(COLOR) ColorMixer { public: - // Having each ColorMixer know about the |previous_mixer| in the pipeline + using MixerGetter = base::RepeatingCallback; + + // Having each ColorMixer know about the |previous mixer| in the pipeline // allows mixers to implement the pipeline directly and simplifies the API, // compared to having each mixer report results (via e.g. Optional) // to the ColorProvider, which would need to query different mixers in order. - explicit ColorMixer(const ColorMixer* previous_mixer = nullptr); + // |input_mixer_getter| can be .Run() to obtain the appropriate mixer to + // query for transform inputs. + explicit ColorMixer(const ColorMixer* previous_mixer = nullptr, + MixerGetter input_mixer_getter = base::NullCallback()); // ColorMixer is movable since it holds both sets and recipes, each of which // might be expensive to copy. ColorMixer(ColorMixer&&) noexcept; @@ -68,6 +75,7 @@ class COMPONENT_EXPORT(COLOR) ColorMixer { ColorSets::const_iterator FindSetWithId(ColorSetId id) const; const ColorMixer* previous_mixer_; + MixerGetter input_mixer_getter_; ColorSets sets_; // This uses std::map instead of base::flat_map since the recipes are inserted diff --git a/chromium/ui/color/color_mixer_unittest.cc b/chromium/ui/color/color_mixer_unittest.cc index 39d45d291c7..8beae2b8b68 100644 --- a/chromium/ui/color/color_mixer_unittest.cc +++ b/chromium/ui/color/color_mixer_unittest.cc @@ -30,7 +30,7 @@ TEST(ColorMixerTest, AddSet) { // Tests that the recipe returned by operator[] is respected by the mixer. TEST(ColorMixerTest, AccessOperator) { ColorMixer mixer; - mixer[kColorTest0] = ColorTransform(SK_ColorGREEN); + mixer[kColorTest0] = {SK_ColorGREEN}; EXPECT_EQ(SK_ColorGREEN, mixer.GetResultColor(kColorTest0)); } @@ -203,7 +203,7 @@ TEST(ColorMixerTest, GetResultColorNoRecipe) { // initial value for its requested color. TEST(ColorMixerTest, GetResultColorNoSet) { ColorMixer mixer; - mixer[kColorTest0] = ColorTransform(SK_ColorGREEN); + mixer[kColorTest0] = {SK_ColorGREEN}; mixer[kColorTest1] = GetColorWithMaxContrast(FromTransformInput()); EXPECT_EQ(SK_ColorGREEN, mixer.GetResultColor(kColorTest0)); EXPECT_NE(gfx::kPlaceholderColor, mixer.GetResultColor(kColorTest1)); @@ -215,8 +215,8 @@ TEST(ColorMixerTest, GetResultColorIgnoresSet) { ColorMixer mixer; mixer.AddSet({kColorSetTest0, {{kColorTest0, SK_ColorWHITE}, {kColorTest1, SK_ColorBLACK}}}); - mixer[kColorTest0] = ColorTransform(SK_ColorGREEN); - mixer[kColorTest1] = ColorTransform(SK_ColorGREEN); + mixer[kColorTest0] = {SK_ColorGREEN}; + mixer[kColorTest1] = {SK_ColorGREEN}; EXPECT_EQ(SK_ColorGREEN, mixer.GetResultColor(kColorTest0)); EXPECT_EQ(SK_ColorGREEN, mixer.GetResultColor(kColorTest1)); } @@ -226,7 +226,7 @@ TEST(ColorMixerTest, GetResultColorIgnoresSet) { TEST(ColorMixerTest, GetResultColorChained) { ColorMixer mixer; mixer.AddSet({kColorSetTest0, {{kColorTest1, SK_ColorWHITE}}}); - mixer[kColorTest0] = ColorTransform(gfx::kGoogleBlue050); + mixer[kColorTest0] = {gfx::kGoogleBlue050}; mixer[kColorTest1] = BlendTowardMaxContrast( GetColorWithMaxContrast(FromTransformInput()), 0x29); mixer[kColorTest2] = @@ -234,5 +234,22 @@ TEST(ColorMixerTest, GetResultColorChained) { EXPECT_EQ(SkColorSetRGB(0x89, 0xB3, 0xF8), mixer.GetResultColor(kColorTest2)); } +// Tests that GetResultColor() will use an input getter, if specified, to source +// input colors for recipes. +TEST(ColorMixerTest, GetResultColorWithInputGetter) { + const ColorMixer* front_mixer; + const auto getter = base::BindRepeating( + [](const ColorMixer** mixer) { return *mixer; }, &front_mixer); + ColorMixer mixer0(nullptr, getter); + ColorMixer mixer1(&mixer0, getter); + front_mixer = &mixer1; + mixer0[kColorTest0] = {SK_ColorWHITE}; + mixer0[kColorTest1] = GetColorWithMaxContrast(kColorTest0); + mixer1[kColorTest0] = {SK_ColorBLACK}; + const SkColor output = mixer0.GetResultColor(kColorTest1); + EXPECT_EQ(output, mixer1.GetResultColor(kColorTest1)); + EXPECT_FALSE(color_utils::IsDark(output)); +} + } // namespace } // namespace ui diff --git a/chromium/ui/color/color_mixers.h b/chromium/ui/color/color_mixers.h index 07647e2718f..3947f8ddd1e 100644 --- a/chromium/ui/color/color_mixers.h +++ b/chromium/ui/color/color_mixers.h @@ -6,6 +6,7 @@ #define UI_COLOR_COLOR_MIXERS_H_ #include "base/component_export.h" +#include "build/build_config.h" namespace ui { @@ -18,23 +19,35 @@ class ColorProvider; // |dark window| should be set if the window for this provider is "dark themed", // e.g. system native dark mode is enabled or the window is incognito. COMPONENT_EXPORT(COLOR) -void AddCoreDefaultColorMixer(ColorProvider* provider, bool dark_window); +void AddCoreDefaultColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast); // Adds a color mixer to |provider| that provide kColorSetNative. // This function should be implemented on a per-platform basis in // relevant subdirectories. COMPONENT_EXPORT(COLOR) -void AddNativeCoreColorMixer(ColorProvider* provider, bool dark_window); +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast); // Adds a color mixer to |provider| that combine the above color sets with // recipes as necessary to produce all colors needed by ui/. -COMPONENT_EXPORT(COLOR) void AddUiColorMixer(ColorProvider* provider); +COMPONENT_EXPORT(COLOR) +void AddUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast); // Adds a color mixer to |provider| that can add to kColorSetNative. // Intended for colors needed by ui/ that this platform overrides but // are outside the set defined in the core mixer. COMPONENT_EXPORT(COLOR) -void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window); +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast); + +COMPONENT_EXPORT(COLOR) +void AddNativePostprocessingMixer(ColorProvider* provider); } // namespace ui diff --git a/chromium/ui/color/color_provider.cc b/chromium/ui/color/color_provider.cc index 9157fbf4f2c..276e2a3fe6f 100644 --- a/chromium/ui/color/color_provider.cc +++ b/chromium/ui/color/color_provider.cc @@ -6,39 +6,77 @@ #include +#include "base/logging.h" #include "ui/color/color_mixer.h" +#include "ui/color/color_provider_utils.h" #include "ui/gfx/color_palette.h" namespace ui { +ColorProvider::ColorProvider() = default; + +ColorProvider::~ColorProvider() = default; + ColorMixer& ColorProvider::AddMixer() { // Adding a mixer could change any of the result colors. cache_.clear(); - // Supply each new mixer with the previous mixer in the pipeline; this way - // GetColor() need not query each mixer in order, but simply ask the last - // mixer for its result, and trust mixers to query each other back up the - // chain as needed. - mixers_.emplace_front(mixers_.empty() ? nullptr : &mixers_.front()); + mixers_.emplace_after(first_postprocessing_mixer_, + GetLastNonPostprocessingMixer(), + base::BindRepeating( + [](const ColorProvider* provider) { + return provider->GetLastNonPostprocessingMixer(); + }, + base::Unretained(this))); + return *std::next(first_postprocessing_mixer_, 1); +} + +ColorMixer& ColorProvider::AddPostprocessingMixer() { + // Adding a mixer could change any of the result colors. + cache_.clear(); + + if (first_postprocessing_mixer_ == mixers_.before_begin()) { + mixers_.emplace_front( + mixers_.empty() ? nullptr : &mixers_.front(), + base::BindRepeating( + [](const ColorProvider* provider) { + return provider->GetLastNonPostprocessingMixer(); + }, + base::Unretained(this))); + first_postprocessing_mixer_ = mixers_.begin(); + } else { + mixers_.emplace_front( + &mixers_.front(), + base::BindRepeating([](const ColorMixer* mixer) { return mixer; }, + base::Unretained(&mixers_.front()))); + } return mixers_.front(); } SkColor ColorProvider::GetColor(ColorId id) const { DCHECK_COLOR_ID_VALID(id); - if (mixers_.empty()) + if (mixers_.empty()) { + DVLOG(2) << "ColorProvider::GetColor: No mixers defined!"; return gfx::kPlaceholderColor; + } // Only compute the result color when it's not already in the cache. auto i = cache_.find(id); - if (i == cache_.end()) + if (i == cache_.end()) { + DVLOG(2) << "ColorProvider::GetColor: Computing color for ColorId: " + << ColorIdName(id); i = cache_.insert({id, mixers_.front().GetResultColor(id)}).first; + } + DVLOG(2) << "ColorProvider::GetColor: ColorId: " << ColorIdName(id) + << " Value: " << SkColorName(i->second); return i->second; } -ColorProvider::ColorProvider() = default; - -ColorProvider::~ColorProvider() = default; +const ColorMixer* ColorProvider::GetLastNonPostprocessingMixer() const { + const auto it = std::next(first_postprocessing_mixer_, 1); + return (it == mixers_.cend()) ? nullptr : &(*it); +} } // namespace ui diff --git a/chromium/ui/color/color_provider.h b/chromium/ui/color/color_provider.h index c735a5e709e..559ed0fcb53 100644 --- a/chromium/ui/color/color_provider.h +++ b/chromium/ui/color/color_provider.h @@ -29,19 +29,34 @@ class COMPONENT_EXPORT(COLOR) ColorProvider { ColorProvider& operator=(const ColorProvider&) = delete; ~ColorProvider(); - // Adds a mixer to the end of the current color pipeline. Returns a reference - // to the added mixer so callers can subsequently add sets and/or recipes. + // Adds a mixer to the current color pipeline after all other + // non-"postprocessing" mixers. Returns a reference to the added mixer so + // callers can subsequently add sets and/or recipes. ColorMixer& AddMixer(); + // Like AddMixer(), but adds at the very end of the color pipeline. + // "Postprocessing" mixers are meant to run after all other mixers and are + // skipped when calling GetUnprocessedColor(). + ColorMixer& AddPostprocessingMixer(); + // Returns the result color for |id| by applying the effects of each mixer in // order. Returns gfx::kPlaceholderColor if no mixer knows how to construct // |id|. SkColor GetColor(ColorId id) const; private: + using Mixers = std::forward_list; + + // Returns the last mixer in the chain that is not a "postprocessing" mixer, + // or nullptr. + const ColorMixer* GetLastNonPostprocessingMixer() const; + // The entire color pipeline, in reverse order (that is, the "last" mixer is // at the front). - std::forward_list mixers_; + Mixers mixers_; + + // The first mixer in the chain that is a "postprocessing" mixer. + Mixers::iterator first_postprocessing_mixer_ = mixers_.before_begin(); // Caches the results of calls to GetColor(). This is invalidated by // AddMixer(). Uses a std::map rather than a base::flat_map since it has diff --git a/chromium/ui/color/color_provider_manager.cc b/chromium/ui/color/color_provider_manager.cc index be2b1b3ed25..0d18cd29572 100644 --- a/chromium/ui/color/color_provider_manager.cc +++ b/chromium/ui/color/color_provider_manager.cc @@ -6,10 +6,18 @@ #include +#include "base/bind.h" #include "base/check.h" +#include "base/logging.h" #include "base/no_destructor.h" #include "base/optional.h" +#include "build/build_config.h" #include "ui/color/color_provider.h" +#include "ui/color/color_provider_utils.h" + +#if !defined(OS_ANDROID) +#include "ui/color/color_mixers.h" +#endif namespace ui { @@ -34,39 +42,80 @@ base::Optional& GetGlobalManager() { } // namespace -ColorProviderManager::ColorProviderManager() = default; +ColorProviderManager::ColorProviderManager() { + ResetColorProviderInitializerList(); +} + ColorProviderManager::~ColorProviderManager() = default; // static ColorProviderManager& ColorProviderManager::Get() { base::Optional& manager = GetGlobalManager(); - if (!manager.has_value()) + 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) { + const bool dark_mode = + color_mode == ColorProviderManager::ColorMode::kDark; + const bool high_contrast = + contrast_mode == ColorProviderManager::ContrastMode::kHigh; + ui::AddCoreDefaultColorMixer(provider, dark_mode, high_contrast); + ui::AddNativeCoreColorMixer(provider, dark_mode, high_contrast); + ui::AddUiColorMixer(provider, dark_mode, high_contrast); + ui::AddNativeUiColorMixer(provider, dark_mode, high_contrast); + ui::AddNativePostprocessingMixer(provider); + })); +#endif // !defined(OS_ANDROID) + } return manager.value(); } +// static +ColorProviderManager& ColorProviderManager::GetForTesting() { + base::Optional& manager = GetGlobalManager(); + if (!manager.has_value()) + manager.emplace(); + return manager.value(); +} + // static void ColorProviderManager::ResetForTesting() { GetGlobalManager().reset(); } -void ColorProviderManager::SetColorProviderInitializer( - ColorProviderInitializer initializer) { - DCHECK(initializer_.is_null()); - DCHECK(color_providers_.empty()); - initializer_ = std::move(initializer); +void ColorProviderManager::ResetColorProviderInitializerList() { + if (!color_providers_.empty()) + color_providers_.clear(); + initializer_list_ = std::make_unique(); + initializer_subscriptions_.clear(); +} + +void ColorProviderManager::AppendColorProviderInitializer( + ColorProviderInitializerList::CallbackType initializer) { + DCHECK(initializer_list_); + if (!color_providers_.empty()) + color_providers_.clear(); + + initializer_subscriptions_.push_back( + initializer_list_->Add(std::move(initializer))); } -ColorProvider* ColorProviderManager::GetColorProviderFor( - ColorMode color_mode, - ContrastMode contrast_mode) { - auto key = ColorProviderKey(color_mode, contrast_mode); +ColorProvider* ColorProviderManager::GetColorProviderFor(ColorProviderKey key) { auto iter = color_providers_.find(key); if (iter == color_providers_.end()) { auto provider = std::make_unique(); - if (!initializer_.is_null()) - initializer_.Run(provider.get(), color_mode, contrast_mode); + DCHECK(initializer_list_); + if (!initializer_list_->empty()) { + DVLOG(2) << "ColorProviderManager: Initializing Color Provider" + << " - ColorMode: " << ColorModeName(std::get(key)) + << " - ContrastMode: " + << ContrastModeName(std::get(key)); + initializer_list_->Notify(provider.get(), std::get(key), + std::get(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 7baa65e90f9..26c1257b0af 100644 --- a/chromium/ui/color/color_provider_manager.h +++ b/chromium/ui/color/color_provider_manager.h @@ -9,6 +9,7 @@ #include #include "base/callback.h" +#include "base/callback_list.h" #include "base/component_export.h" #include "base/containers/flat_map.h" @@ -31,31 +32,38 @@ class COMPONENT_EXPORT(COLOR) ColorProviderManager { kNormal, kHigh, }; - using ColorProviderInitializer = - base::RepeatingCallback; + using ColorProviderKey = std::tuple; + using ColorProviderInitializerList = base::RepeatingCallbackList< + void(ColorProvider*, ColorMode, ContrastMode)>; ColorProviderManager(const ColorProviderManager&) = delete; ColorProviderManager& operator=(const ColorProviderManager&) = delete; static ColorProviderManager& Get(); + static ColorProviderManager& GetForTesting(); static void ResetForTesting(); - // Sets the initializer for all ColorProviders returned from - // GetColorProviderFor(). - void SetColorProviderInitializer(ColorProviderInitializer initializer); + // Resets the current `initializer_list_`. + void ResetColorProviderInitializerList(); + + // Appends `initializer` to the end of the current `initializer_list_`. + void AppendColorProviderInitializer( + ColorProviderInitializerList::CallbackType Initializer); - // Returns a color provider for |color_mode| and |contrast_mode|, creating one - // if necessary. - ColorProvider* GetColorProviderFor(ColorMode color_mode, - ContrastMode contrast_mode); + // Returns a color provider for |key|, creating one if necessary. + ColorProvider* GetColorProviderFor(ColorProviderKey key); protected: ColorProviderManager(); virtual ~ColorProviderManager(); private: - using ColorProviderKey = std::tuple; - ColorProviderInitializer initializer_; + // Holds the chain of ColorProvider initializer callbacks. + std::unique_ptr initializer_list_; + + // Holds the subscriptions for initializers in the `initializer_list_`. + std::vector initializer_subscriptions_; + base::flat_map> color_providers_; }; diff --git a/chromium/ui/color/color_provider_manager_unittest.cc b/chromium/ui/color/color_provider_manager_unittest.cc index c7cd30b6a9d..46a007eace6 100644 --- a/chromium/ui/color/color_provider_manager_unittest.cc +++ b/chromium/ui/color/color_provider_manager_unittest.cc @@ -18,7 +18,7 @@ namespace { class ColorProviderManagerTest : public testing::Test { public: - ColorProviderManagerTest() = default; + ColorProviderManagerTest() { ColorProviderManager::ResetForTesting(); } ColorProviderManagerTest(const ColorProviderManagerTest&) = delete; ColorProviderManagerTest& operator=(const ColorProviderManagerTest&) = delete; ~ColorProviderManagerTest() override { @@ -27,9 +27,9 @@ class ColorProviderManagerTest : public testing::Test { }; ColorProvider* GetLightNormalColorProvider() { - return ColorProviderManager::Get().GetColorProviderFor( - ColorProviderManager::ColorMode::kLight, - ColorProviderManager::ContrastMode::kNormal); + return ColorProviderManager::GetForTesting().GetColorProviderFor( + {ColorProviderManager::ColorMode::kLight, + ColorProviderManager::ContrastMode::kNormal}); } } // namespace @@ -47,9 +47,10 @@ TEST_F(ColorProviderManagerTest, Persistence) { // Verifies that the initializer is called for each newly created color // provider. TEST_F(ColorProviderManagerTest, SetInitializer) { - ColorProviderManager::Get().SetColorProviderInitializer(base::BindRepeating( - [](ColorProvider* provider, ColorProviderManager::ColorMode, - ColorProviderManager::ContrastMode) { + ColorProviderManager::GetForTesting().AppendColorProviderInitializer( + base::BindRepeating([](ColorProvider* provider, + ColorProviderManager::ColorMode, + ColorProviderManager::ContrastMode) { provider->AddMixer().AddSet( {kColorSetTest0, {{kColorTest0, SK_ColorBLUE}}}); })); diff --git a/chromium/ui/color/color_provider_unittest.cc b/chromium/ui/color/color_provider_unittest.cc index 381faa33fd5..193080e10eb 100644 --- a/chromium/ui/color/color_provider_unittest.cc +++ b/chromium/ui/color/color_provider_unittest.cc @@ -5,8 +5,11 @@ #include "ui/color/color_provider.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/color/color_recipe.h" #include "ui/color/color_test_ids.h" +#include "ui/color/color_transform.h" #include "ui/gfx/color_palette.h" +#include "ui/gfx/color_utils.h" namespace ui { namespace { @@ -55,5 +58,41 @@ TEST(ColorProviderTest, Caching) { EXPECT_EQ(SK_ColorRED, provider.GetColor(kColorTest0)); } +// Tests that with both a standard and a "postprocessing" mixer, GetColor() +// takes both into account. +TEST(ColorProviderTest, WithProcessing) { + ColorProvider provider; + provider.AddMixer().AddSet({kColorSetTest0, {{kColorTest0, SK_ColorBLACK}}}); + provider.AddPostprocessingMixer()[kColorTest0] = + GetColorWithMaxContrast(FromTransformInput()); + EXPECT_EQ(SK_ColorWHITE, provider.GetColor(kColorTest0)); +} + +// Tests that if a color is redefined by a later mixer, an earlier mixer will +// "see" the result. +TEST(ColorProviderTest, Redefinition) { + ColorProvider provider; + ColorMixer& mixer0 = provider.AddMixer(); + mixer0[kColorTest0] = {SK_ColorBLACK}; + mixer0[kColorTest1] = AlphaBlend(SK_ColorRED, kColorTest0, 0x01); + provider.AddMixer()[kColorTest0] = {SK_ColorWHITE}; + EXPECT_EQ(SK_ColorWHITE, provider.GetColor(kColorTest0)); + EXPECT_FALSE(color_utils::IsDark(provider.GetColor(kColorTest1))); +} + +// Tests that "postprocessing" mixers are skipped for the purposes of color +// lookup during intermediate stages. +TEST(ColorProviderTest, RedefinitionWithProcessing) { + ColorProvider provider; + ColorMixer& mixer0 = provider.AddMixer(); + mixer0[kColorTest0] = {SK_ColorBLACK}; + mixer0[kColorTest1] = AlphaBlend(SK_ColorRED, kColorTest0, 0x01); + provider.AddMixer()[kColorTest0] = {SK_ColorWHITE}; + provider.AddPostprocessingMixer()[kColorTest0] = + GetColorWithMaxContrast(FromTransformInput()); + EXPECT_NE(SK_ColorWHITE, provider.GetColor(kColorTest0)); + EXPECT_FALSE(color_utils::IsDark(provider.GetColor(kColorTest1))); +} + } // namespace } // namespace ui diff --git a/chromium/ui/color/color_provider_utils.cc b/chromium/ui/color/color_provider_utils.cc new file mode 100644 index 00000000000..1532ad29fb5 --- /dev/null +++ b/chromium/ui/color/color_provider_utils.cc @@ -0,0 +1,208 @@ +// 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/color/color_provider_utils.h" + +#include "base/containers/fixed_flat_map.h" +#include "base/strings/stringprintf.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/color_utils.h" + +namespace ui { + +base::StringPiece ColorModeName(ColorProviderManager::ColorMode color_mode) { + switch (color_mode) { + case ColorProviderManager::ColorMode::kLight: + return "kLight"; + case ColorProviderManager::ColorMode::kDark: + return "kDark"; + default: + return ""; + } +} + +base::StringPiece ContrastModeName( + ColorProviderManager::ContrastMode contrast_mode) { + switch (contrast_mode) { + case ColorProviderManager::ContrastMode::kNormal: + return "kNormal"; + case ColorProviderManager::ContrastMode::kHigh: + return "kHigh"; + default: + return ""; + } +} + +#define E1(enum_name) \ + { enum_name, #enum_name } +#define E2(enum_name, old_enum_name) \ + { enum_name, #enum_name } +#define E3(enum_name, old_enum_name, enum_value) \ + { enum_name, #enum_name } +#define E_CPONLY(...) E(__VA_ARGS__) +#define GET_E(_1, _2, _3, macro_name, ...) macro_name +#define E(...) GET_E(__VA_ARGS__, E3, E2, E1)(__VA_ARGS__), + +base::StringPiece ColorIdName(ColorId color_id) { + static constexpr const auto color_id_map = + base::MakeFixedFlatMap({COLOR_IDS}); + auto* i = color_id_map.find(color_id); + if (i != color_id_map.cend()) + return i->second; + return ""; +} + +#undef E1 +#undef E2 +#undef E3 +#undef E_CPONLY +#undef GET_E +#undef E + +base::StringPiece ColorSetIdName(ColorSetId color_set_id) { + // Since we're returning a StringPiece we need a stable location to store the + // string we may construct below. This is only for immediate logging. The + // behavior is undefined if the result is retained beyond the scope in which + // this function is called. + static char color_set_id_string[20] = ""; + switch (color_set_id) { + case kColorSetNative: + return "kColorSetNative"; + case kColorSetCoreDefaults: + return "kColorSetCoreDefaults"; + default: { + std::snprintf(color_set_id_string, sizeof(color_set_id_string), + "ColorSetId(%d)", color_set_id); + return color_set_id_string; + } + } +} + +std::string SkColorName(SkColor color) { + static const auto color_name_map = + base::MakeFixedFlatMap({ + {gfx::kGoogleBlue050, "kGoogleBlue050"}, + {gfx::kGoogleBlue100, "kGoogleBlue100"}, + {gfx::kGoogleBlue200, "kGoogleBlue200"}, + {gfx::kGoogleBlue300, "kGoogleBlue300"}, + {gfx::kGoogleBlue400, "kGoogleBlue400"}, + {gfx::kGoogleBlue500, "kGoogleBlue500"}, + {gfx::kGoogleBlue600, "kGoogleBlue600"}, + {gfx::kGoogleBlue700, "kGoogleBlue700"}, + {gfx::kGoogleBlue800, "kGoogleBlue800"}, + {gfx::kGoogleBlue900, "kGoogleBlue900"}, + {gfx::kGoogleBlueDark400, "kGoogleBlueDark400"}, + {gfx::kGoogleBlueDark600, "kGoogleBlueDark600"}, + {gfx::kGoogleRed050, "kGoogleRed050"}, + {gfx::kGoogleRed100, "kGoogleRed100"}, + {gfx::kGoogleRed200, "kGoogleRed200"}, + {gfx::kGoogleRed300, "kGoogleRed300"}, + {gfx::kGoogleRed400, "kGoogleRed400"}, + {gfx::kGoogleRed500, "kGoogleRed500"}, + {gfx::kGoogleRed600, "kGoogleRed600"}, + {gfx::kGoogleRed700, "kGoogleRed700"}, + {gfx::kGoogleRed800, "kGoogleRed800"}, + {gfx::kGoogleRed900, "kGoogleRed900"}, + {gfx::kGoogleRedDark500, "kGoogleRedDark500"}, + {gfx::kGoogleRedDark600, "kGoogleRedDark600"}, + {gfx::kGoogleRedDark800, "kGoogleRedDark800"}, + {gfx::kGoogleGreen050, "kGoogleGreen050"}, + {gfx::kGoogleGreen100, "kGoogleGreen100"}, + {gfx::kGoogleGreen200, "kGoogleGreen200"}, + {gfx::kGoogleGreen300, "kGoogleGreen300"}, + {gfx::kGoogleGreen400, "kGoogleGreen400"}, + {gfx::kGoogleGreen500, "kGoogleGreen500"}, + {gfx::kGoogleGreen600, "kGoogleGreen600"}, + {gfx::kGoogleGreen700, "kGoogleGreen700"}, + {gfx::kGoogleGreen800, "kGoogleGreen800"}, + {gfx::kGoogleGreen900, "kGoogleGreen900"}, + {gfx::kGoogleGreenDark500, "kGoogleGreenDark500"}, + {gfx::kGoogleGreenDark600, "kGoogleGreenDark600"}, + {gfx::kGoogleYellow050, "kGoogleYellow050"}, + {gfx::kGoogleYellow100, "kGoogleYellow100"}, + {gfx::kGoogleYellow200, "kGoogleYellow200"}, + {gfx::kGoogleYellow300, "kGoogleYellow300"}, + {gfx::kGoogleYellow400, "kGoogleYellow400"}, + {gfx::kGoogleYellow500, "kGoogleYellow500"}, + {gfx::kGoogleYellow600, "kGoogleYellow600"}, + {gfx::kGoogleYellow700, "kGoogleYellow700"}, + {gfx::kGoogleYellow800, "kGoogleYellow800"}, + {gfx::kGoogleYellow900, "kGoogleYellow900"}, + {gfx::kGoogleGrey050, "kGoogleGrey050"}, + {gfx::kGoogleGrey100, "kGoogleGrey100"}, + {gfx::kGoogleGrey200, "kGoogleGrey200"}, + {gfx::kGoogleGrey300, "kGoogleGrey300"}, + {gfx::kGoogleGrey400, "kGoogleGrey400"}, + {gfx::kGoogleGrey500, "kGoogleGrey500"}, + {gfx::kGoogleGrey600, "kGoogleGrey600"}, + {gfx::kGoogleGrey700, "kGoogleGrey700"}, + {gfx::kGoogleGrey800, "kGoogleGrey800"}, + {gfx::kGoogleGrey900, "kGoogleGrey900"}, + {gfx::kGoogleOrange050, "kGoogleOrange050"}, + {gfx::kGoogleOrange100, "kGoogleOrange100"}, + {gfx::kGoogleOrange200, "kGoogleOrange200"}, + {gfx::kGoogleOrange300, "kGoogleOrange300"}, + {gfx::kGoogleOrange400, "kGoogleOrange400"}, + {gfx::kGoogleOrange500, "kGoogleOrange500"}, + {gfx::kGoogleOrange600, "kGoogleOrange600"}, + {gfx::kGoogleOrange700, "kGoogleOrange700"}, + {gfx::kGoogleOrange800, "kGoogleOrange800"}, + {gfx::kGoogleOrange900, "kGoogleOrange900"}, + {gfx::kGooglePink050, "kGooglePink050"}, + {gfx::kGooglePink100, "kGooglePink100"}, + {gfx::kGooglePink200, "kGooglePink200"}, + {gfx::kGooglePink300, "kGooglePink300"}, + {gfx::kGooglePink400, "kGooglePink400"}, + {gfx::kGooglePink500, "kGooglePink500"}, + {gfx::kGooglePink600, "kGooglePink600"}, + {gfx::kGooglePink700, "kGooglePink700"}, + {gfx::kGooglePink800, "kGooglePink800"}, + {gfx::kGooglePink900, "kGooglePink900"}, + {gfx::kGooglePurple050, "kGooglePurple050"}, + {gfx::kGooglePurple100, "kGooglePurple100"}, + {gfx::kGooglePurple200, "kGooglePurple200"}, + {gfx::kGooglePurple300, "kGooglePurple300"}, + {gfx::kGooglePurple400, "kGooglePurple400"}, + {gfx::kGooglePurple500, "kGooglePurple500"}, + {gfx::kGooglePurple600, "kGooglePurple600"}, + {gfx::kGooglePurple700, "kGooglePurple700"}, + {gfx::kGooglePurple800, "kGooglePurple800"}, + {gfx::kGooglePurple900, "kGooglePurple900"}, + {gfx::kGoogleCyan050, "kGoogleCyan050"}, + {gfx::kGoogleCyan100, "kGoogleCyan100"}, + {gfx::kGoogleCyan200, "kGoogleCyan200"}, + {gfx::kGoogleCyan300, "kGoogleCyan300"}, + {gfx::kGoogleCyan400, "kGoogleCyan400"}, + {gfx::kGoogleCyan500, "kGoogleCyan500"}, + {gfx::kGoogleCyan600, "kGoogleCyan600"}, + {gfx::kGoogleCyan700, "kGoogleCyan700"}, + {gfx::kGoogleCyan800, "kGoogleCyan800"}, + {gfx::kGoogleCyan900, "kGoogleCyan900"}, + {SK_ColorTRANSPARENT, "SK_ColorTRANSPARENT"}, + {SK_ColorBLACK, "SK_ColorBLACK"}, + {SK_ColorDKGRAY, "SK_ColorDKGRAY"}, + {SK_ColorGRAY, "SK_ColorGRAY"}, + {SK_ColorLTGRAY, "SK_ColorLTGRAY"}, + {SK_ColorWHITE, "SK_ColorWHITE"}, + {SK_ColorRED, "kPlaceholderColor(SK_ColorRED)"}, + {SK_ColorGREEN, "SK_ColorGREEN"}, + {SK_ColorBLUE, "SK_ColorBLUE"}, + {SK_ColorYELLOW, "SK_ColorYELLOW"}, + {SK_ColorCYAN, "SK_ColorCYAN"}, + {SK_ColorMAGENTA, "SK_ColorMAGENTA"}, + }); + auto color_with_alpha = color; + color = SkColorSetA(color, SK_AlphaOPAQUE); + auto* i = color_name_map.find(color); + if (i != color_name_map.cend()) { + if (SkColorGetA(color_with_alpha) == SkColorGetA(color)) + return i->second; + return base::StringPrintf("rgba(%s, %f)", i->second, + 1.0 / SkColorGetA(color_with_alpha)); + } + return color_utils::SkColorToRgbaString(color); +} + +} // namespace ui diff --git a/chromium/ui/color/color_provider_utils.h b/chromium/ui/color/color_provider_utils.h new file mode 100644 index 00000000000..842c40189ab --- /dev/null +++ b/chromium/ui/color/color_provider_utils.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_COLOR_COLOR_PROVIDER_UTILS_H_ +#define UI_COLOR_COLOR_PROVIDER_UTILS_H_ + +#include + +#include "base/component_export.h" +#include "base/strings/string_piece.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/color/color_id.h" +#include "ui/color/color_provider_manager.h" + +namespace ui { + +// The following functions convert various values to strings intended for +// logging. Do not retain the results for longer than the scope in which these +// functions are called. + +// Converts the ColorMode. +base::StringPiece COMPONENT_EXPORT(COLOR) + ColorModeName(ColorProviderManager::ColorMode color_mode); + +// Converts the ContrastMode. +base::StringPiece COMPONENT_EXPORT(COLOR) + ContrastModeName(ColorProviderManager::ContrastMode contrast_mode); + +// Converts ColorId. +base::StringPiece COMPONENT_EXPORT(COLOR) ColorIdName(ColorId color_id); + +// Converts ColorSetId. +base::StringPiece COMPONENT_EXPORT(COLOR) + ColorSetIdName(ColorSetId color_set_id); + +// Converts SkColor to string. Check if color matches a standard color palette +// value and return it as a string. Otherwise return as an rgba(xx, xxx, xxx, +// xxx) string. +std::string COMPONENT_EXPORT(COLOR) SkColorName(SkColor color); + +} // namespace ui + +#endif // UI_COLOR_COLOR_PROVIDER_UTILS_H_ \ No newline at end of file diff --git a/chromium/ui/color/color_recipe.cc b/chromium/ui/color/color_recipe.cc index b7d27554209..74d78cdaac5 100644 --- a/chromium/ui/color/color_recipe.cc +++ b/chromium/ui/color/color_recipe.cc @@ -6,7 +6,9 @@ #include +#include "base/logging.h" #include "ui/color/color_mixer.h" +#include "ui/color/color_provider_utils.h" namespace ui { @@ -33,9 +35,12 @@ ColorRecipe& ColorRecipe::operator+=(const ColorTransform& transform) { SkColor ColorRecipe::GenerateResult(SkColor input, const ColorMixer& mixer) const { + SkColor output_color = input; for (const auto& transform : transforms_) - input = transform.Run(input, mixer); - return input; + output_color = transform.Run(output_color, mixer); + DVLOG(2) << "ColorRecipe::GenerateResult: Input Color " << SkColorName(input) + << " Result Color " << SkColorName(output_color); + return output_color; } ColorRecipe operator+(ColorRecipe recipe, const ColorTransform& transform) { diff --git a/chromium/ui/color/color_transform.cc b/chromium/ui/color/color_transform.cc index a415d2c6316..e433af7d7bd 100644 --- a/chromium/ui/color/color_transform.cc +++ b/chromium/ui/color/color_transform.cc @@ -5,8 +5,11 @@ #include "ui/color/color_transform.h" #include "base/bind.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/color/color_mixer.h" +#include "ui/color/color_provider_utils.h" namespace ui { @@ -15,7 +18,13 @@ ColorTransform::ColorTransform(Callback callback) ColorTransform::ColorTransform(SkColor color) { const auto generator = [](SkColor color, SkColor input_color, - const ColorMixer& mixer) { return color; }; + const ColorMixer& mixer) { + DVLOG(2) << "ColorTransform From Color:" + << " Input Color:" << SkColorName(input_color) + << " Color: " << SkColorName(color) + << " Result Color: " << SkColorName(color); + return color; + }; callback_ = base::BindRepeating(generator, color); } @@ -23,7 +32,12 @@ ColorTransform::ColorTransform(ColorId id) { DCHECK_COLOR_ID_VALID(id); const auto generator = [](ColorId id, SkColor input_color, const ColorMixer& mixer) { - return mixer.GetResultColor(id); + SkColor result_color = mixer.GetResultColor(id); + DVLOG(2) << "ColorTransform FromMixer:" + << " Input Color:" << SkColorName(input_color) + << " Color Id: " << ColorIdName(id) + << " Result Color: " << SkColorName(result_color); + return result_color; }; callback_ = base::BindRepeating(generator, id); } @@ -45,9 +59,19 @@ ColorTransform AlphaBlend(ColorTransform foreground_transform, const auto generator = [](ColorTransform foreground_transform, ColorTransform background_transform, SkAlpha alpha, SkColor input_color, const ColorMixer& mixer) { - return color_utils::AlphaBlend(foreground_transform.Run(input_color, mixer), - background_transform.Run(input_color, mixer), - alpha); + const SkColor foreground_color = + foreground_transform.Run(input_color, mixer); + const SkColor background_color = + background_transform.Run(input_color, mixer); + const SkColor result_color = + color_utils::AlphaBlend(foreground_color, background_color, alpha); + DVLOG(2) << "ColorTransform AlphaBlend:" + << " Input Color: " << SkColorName(input_color) + << " FG Transform: " << SkColorName(foreground_color) + << " BG Transform: " << SkColorName(background_color) + << " Alpha: " << base::NumberToString(alpha) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(foreground_transform), std::move(background_transform), alpha); @@ -73,10 +97,21 @@ ColorTransform BlendForMinContrast( high_contrast_foreground_transform.value().Run( input_color, mixer)) : base::nullopt; - return color_utils::BlendForMinContrast( - foreground_color, background_color, high_contrast_foreground, - contrast_ratio) - .color; + const SkColor result_color = + color_utils::BlendForMinContrast(foreground_color, background_color, + high_contrast_foreground, + contrast_ratio) + .color; + DVLOG(2) << "ColorTransform BlendForMinContrast:" + << " FG Transform Color: " << SkColorName(foreground_color) + << " BG Transform Color: " << SkColorName(background_color) + << " High Contrast Foreground: " + << (high_contrast_foreground.has_value() + ? SkColorName(high_contrast_foreground.value()) + : "") + << " Contrast Ratio: " << base::NumberToString(contrast_ratio) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(foreground_transform), std::move(background_transform), @@ -93,8 +128,15 @@ ColorTransform BlendForMinContrastWithSelf(ColorTransform transform, ColorTransform BlendTowardMaxContrast(ColorTransform transform, SkAlpha alpha) { const auto generator = [](ColorTransform transform, SkAlpha alpha, SkColor input_color, const ColorMixer& mixer) { - return color_utils::BlendTowardMaxContrast( - transform.Run(input_color, mixer), alpha); + const SkColor transform_color = transform.Run(input_color, mixer); + const SkColor result_color = + color_utils::BlendTowardMaxContrast(transform_color, alpha); + DVLOG(2) << "ColorTransform BlendTowardMaxContrast:" + << " Input Color:" << SkColorName(input_color) + << " Transform Color: " << SkColorName(transform_color) + << " Alpha: " << base::NumberToString(alpha) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(transform), alpha); } @@ -109,9 +151,18 @@ ColorTransform ContrastInvert(ColorTransform transform) { color_utils::GetEndpointColorWithMinContrast(foreground); const float contrast_ratio = color_utils::GetContrastRatio(foreground, far_endpoint); - return color_utils::BlendForMinContrast(foreground, near_endpoint, - base::nullopt, contrast_ratio) - .color; + const SkColor result_color = + color_utils::BlendForMinContrast(foreground, near_endpoint, + base::nullopt, contrast_ratio) + .color; + DVLOG(2) << "ColorTransform ContrastInvert:" + << " Input Color: " << SkColorName(input_color) + << " Foreground: " << SkColorName(foreground) + << " Far End: " << SkColorName(far_endpoint) + << " Near End: " << SkColorName(near_endpoint) + << " Contrast Ratio: " << base::NumberToString(contrast_ratio) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(transform)); } @@ -119,8 +170,14 @@ ColorTransform ContrastInvert(ColorTransform transform) { ColorTransform DeriveDefaultIconColor(ColorTransform transform) { const auto generator = [](ColorTransform transform, SkColor input_color, const ColorMixer& mixer) { - return color_utils::DeriveDefaultIconColor( - transform.Run(input_color, mixer)); + const SkColor transform_color = transform.Run(input_color, mixer); + const SkColor result_color = + color_utils::DeriveDefaultIconColor(transform_color); + DVLOG(2) << "ColorTransform DeriveDefaultIconColor:" + << " Input Color: " << SkColorName(input_color) + << " Transform Color: " << SkColorName(transform_color) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(transform)); } @@ -130,13 +187,20 @@ ColorTransform FromOriginalColorFromSet(ColorId id, ColorSetId set_id) { DCHECK_COLOR_SET_ID_VALID(set_id); const auto generator = [](ColorId id, ColorSetId set_id, SkColor input_color, const ColorMixer& mixer) { - return mixer.GetOriginalColorFromSet(id, set_id); + SkColor result_color = mixer.GetOriginalColorFromSet(id, set_id); + DVLOG(2) << "ColorTransform FromOriginalColorFromSet:" + << " Color Id: " << ColorIdName(id) + << " ColorSet Id: " << ColorSetIdName(set_id) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, id, set_id); } ColorTransform FromTransformInput() { const auto generator = [](SkColor input_color, const ColorMixer& mixer) { + DVLOG(2) << "ColorTransform FromTransformInput: " + << " Input/Result Color: " << SkColorName(input_color); return input_color; }; return base::BindRepeating(generator); @@ -145,8 +209,14 @@ ColorTransform FromTransformInput() { ColorTransform GetColorWithMaxContrast(ColorTransform transform) { const auto generator = [](ColorTransform transform, SkColor input_color, const ColorMixer& mixer) { - return color_utils::GetColorWithMaxContrast( - transform.Run(input_color, mixer)); + const SkColor transform_color = transform.Run(input_color, mixer); + const SkColor result_color = + color_utils::GetColorWithMaxContrast(transform_color); + DVLOG(2) << "ColorTransform GetColorWithMaxContrast:" + << " Input Color: " << SkColorName(input_color) + << " Transform Color: " << SkColorName(transform_color) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(transform)); } @@ -156,9 +226,18 @@ ColorTransform GetResultingPaintColor(ColorTransform foreground_transform, const auto generator = [](ColorTransform foreground_transform, ColorTransform background_transform, SkColor input_color, const ColorMixer& mixer) { - return color_utils::GetResultingPaintColor( - foreground_transform.Run(input_color, mixer), - background_transform.Run(input_color, mixer)); + const SkColor foreground_color = + foreground_transform.Run(input_color, mixer); + const SkColor background_color = + background_transform.Run(input_color, mixer); + const SkColor result_color = + color_utils::GetResultingPaintColor(foreground_color, background_color); + DVLOG(2) << "ColorTransform GetResultingPaintColor:" + << " Input Color: " << SkColorName(input_color) + << " FG Transform Color: " << SkColorName(foreground_color) + << " BG Transform Color: " << SkColorName(background_color) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(foreground_transform), std::move(background_transform)); @@ -176,7 +255,13 @@ ColorTransform SelectBasedOnDarkInput( const auto& output_transform = color_utils::IsDark(color) ? output_transform_for_dark_input : output_transform_for_light_input; - return output_transform.Run(input_color, mixer); + const SkColor result_color = output_transform.Run(input_color, mixer); + DVLOG(2) << "ColorTransform SelectBasedOnDarkInput:" + << " Input Color: " << SkColorName(input_color) + << " Input Transform: " << SkColorName(color) + << " IsDark: " << (color_utils::IsDark(color) ? "true" : "false") + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(input_transform), std::move(output_transform_for_dark_input), @@ -186,7 +271,14 @@ ColorTransform SelectBasedOnDarkInput( ColorTransform SetAlpha(ColorTransform transform, SkAlpha alpha) { const auto generator = [](ColorTransform transform, SkAlpha alpha, SkColor input_color, const ColorMixer& mixer) { - return SkColorSetA(transform.Run(input_color, mixer), alpha); + const SkColor transform_color = transform.Run(input_color, mixer); + const SkColor result_color = SkColorSetA(transform_color, alpha); + DVLOG(2) << "ColorTransform SetAlpha:" + << " Input Color: " << SkColorName(input_color) + << " Transform Color: " << SkColorName(transform_color) + << " Alpha: " << base::NumberToString(alpha) + << " Result Color: " << SkColorName(result_color); + return result_color; }; return base::BindRepeating(generator, std::move(transform), alpha); } diff --git a/chromium/ui/color/color_transform.h b/chromium/ui/color/color_transform.h index efa45e3bb62..5d954842b4b 100644 --- a/chromium/ui/color/color_transform.h +++ b/chromium/ui/color/color_transform.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/optional.h" +#include "build/build_config.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/color/color_id.h" #include "ui/gfx/color_utils.h" @@ -116,6 +117,11 @@ ColorTransform SelectBasedOnDarkInput( COMPONENT_EXPORT(COLOR) ColorTransform SetAlpha(ColorTransform transform, SkAlpha alpha); +#if defined(OS_MAC) +COMPONENT_EXPORT(COLOR) +ColorTransform ApplySystemControlTintIfNeeded(); +#endif + } // namespace ui #endif // UI_COLOR_COLOR_TRANSFORM_H_ diff --git a/chromium/ui/color/core_default_color_mixer.cc b/chromium/ui/color/core_default_color_mixer.cc index 184423b8254..dda5851ad20 100644 --- a/chromium/ui/color/core_default_color_mixer.cc +++ b/chromium/ui/color/core_default_color_mixer.cc @@ -4,6 +4,7 @@ #include "ui/color/color_mixers.h" +#include "base/logging.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/color/color_id.h" #include "ui/color/color_mixer.h" @@ -19,26 +20,24 @@ namespace { // TODO(pkasting): Construct colors from contrast ratios // TODO(pkasting): Construct palette from accent, key, tint/bg, shade/fg colors -ColorMixer& AddMixerForDarkMode(ColorProvider* provider) { +ColorMixer& AddMixerForDarkMode(ColorProvider* provider, bool high_contrast) { ColorMixer& mixer = provider->AddMixer(); - mixer.AddSet( - {kColorSetCoreDefaults, - { - {kColorAccent, gfx::kGoogleBlue300}, - {kColorAlertHighSeverity, gfx::kGoogleRed300}, - {kColorAlertLowSeverity, gfx::kGoogleGreen300}, - {kColorAlertMediumSeverity, gfx::kGoogleYellow300}, - {kColorMidground, gfx::kGoogleGrey800}, - {kColorPrimaryBackground, SkColorSetRGB(0x29, 0x2A, 0x2D)}, - {kColorPrimaryForeground, gfx::kGoogleGrey200}, - {kColorSecondaryForeground, gfx::kGoogleGrey500}, - {kColorSubtleEmphasisBackground, SkColorSetRGB(0x32, 0x36, 0x39)}, - {kColorTextSelectionBackground, gfx::kGoogleBlue800}, - }}); + mixer.AddSet({kColorSetCoreDefaults, + { + {kColorAccent, gfx::kGoogleBlue300}, + {kColorAlertHighSeverity, gfx::kGoogleRed300}, + {kColorAlertLowSeverity, gfx::kGoogleGreen300}, + {kColorAlertMediumSeverity, gfx::kGoogleYellow300}, + {kColorItemHighlight, gfx::kGoogleBlue400}, + {kColorMidground, gfx::kGoogleGrey800}, + {kColorPrimaryBackground, SkColorSetRGB(0x29, 0x2A, 0x2D)}, + {kColorPrimaryForeground, gfx::kGoogleGrey200}, + {kColorSecondaryForeground, gfx::kGoogleGrey500}, + }}); return mixer; } -ColorMixer& AddMixerForLightMode(ColorProvider* provider) { +ColorMixer& AddMixerForLightMode(ColorProvider* provider, bool high_contrast) { ColorMixer& mixer = provider->AddMixer(); mixer.AddSet({kColorSetCoreDefaults, { @@ -46,26 +45,45 @@ ColorMixer& AddMixerForLightMode(ColorProvider* provider) { {kColorAlertHighSeverity, gfx::kGoogleRed600}, {kColorAlertLowSeverity, gfx::kGoogleGreen700}, {kColorAlertMediumSeverity, gfx::kGoogleYellow700}, + {kColorItemHighlight, gfx::kGoogleBlue500}, {kColorMidground, gfx::kGoogleGrey300}, {kColorPrimaryBackground, SK_ColorWHITE}, {kColorPrimaryForeground, gfx::kGoogleGrey900}, {kColorSecondaryForeground, gfx::kGoogleGrey700}, - {kColorSubtleEmphasisBackground, gfx::kGoogleGrey050}, - {kColorTextSelectionBackground, gfx::kGoogleBlue200}, }}); return mixer; } } // namespace -void AddCoreDefaultColorMixer(ColorProvider* provider, bool dark_window) { - ColorMixer& mixer = dark_window ? AddMixerForDarkMode(provider) - : AddMixerForLightMode(provider); +void AddCoreDefaultColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { + DVLOG(2) << "Adding CoreDefaultColorMixer to ColorProvider for " + << (dark_window ? "Dark" : "Light") + << (high_contrast ? " High Contrast" : "") << " window."; + ColorMixer& mixer = dark_window + ? AddMixerForDarkMode(provider, high_contrast) + : AddMixerForLightMode(provider, high_contrast); mixer[kColorDisabledForeground] = BlendForMinContrast( gfx::kGoogleGrey600, kColorPrimaryBackground, kColorPrimaryForeground); + mixer[kColorEndpointBackground] = + GetColorWithMaxContrast(kColorEndpointForeground); + mixer[kColorEndpointForeground] = + GetColorWithMaxContrast(kColorPrimaryBackground); mixer[kColorItemSelectionBackground] = - BlendForMinContrastWithSelf(kColorPrimaryBackground, 1.67f); - // TODO(pkasting): High contrast? + AlphaBlend(kColorAccent, kColorPrimaryBackground, 0x3C); + mixer[kColorMenuSelectionBackground] = + AlphaBlend(kColorEndpointForeground, kColorPrimaryBackground, + gfx::kGoogleGreyAlpha200); + mixer[kColorSubtleAccent] = AlphaBlend(kColorAccent, kColorPrimaryBackground, + gfx::kGoogleGreyAlpha400); + mixer[kColorSubtleEmphasisBackground] = + BlendTowardMaxContrast(kColorPrimaryBackground, gfx::kGoogleGreyAlpha100); + mixer[kColorTextSelectionBackground] = AlphaBlend( + kColorAccent, kColorPrimaryBackground, gfx::kGoogleGreyAlpha500); + mixer[kColorTextSelectionForeground] = + GetColorWithMaxContrast(kColorTextSelectionBackground); } } // namespace ui diff --git a/chromium/ui/color/cros/native_color_mixers.cc b/chromium/ui/color/cros/native_color_mixers.cc index 2ea973bff1f..e8a68f69376 100644 --- a/chromium/ui/color/cros/native_color_mixers.cc +++ b/chromium/ui/color/cros/native_color_mixers.cc @@ -8,12 +8,18 @@ namespace ui { -void AddNativeCoreColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { NOTIMPLEMENTED(); } -void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { NOTIMPLEMENTED(); } +void AddNativePostprocessingMixer(ColorProvider* provider) {} + } // namespace ui diff --git a/chromium/ui/color/fuchsia/native_color_mixers.cc b/chromium/ui/color/fuchsia/native_color_mixers.cc index 2ea973bff1f..e8a68f69376 100644 --- a/chromium/ui/color/fuchsia/native_color_mixers.cc +++ b/chromium/ui/color/fuchsia/native_color_mixers.cc @@ -8,12 +8,18 @@ namespace ui { -void AddNativeCoreColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { NOTIMPLEMENTED(); } -void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { NOTIMPLEMENTED(); } +void AddNativePostprocessingMixer(ColorProvider* provider) {} + } // namespace ui diff --git a/chromium/ui/color/ios/native_color_mixers.mm b/chromium/ui/color/ios/native_color_mixers.mm new file mode 100644 index 00000000000..e8a68f69376 --- /dev/null +++ b/chromium/ui/color/ios/native_color_mixers.mm @@ -0,0 +1,25 @@ +// 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/color/color_mixers.h" + +#include "base/notreached.h" + +namespace ui { + +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { + NOTIMPLEMENTED(); +} + +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { + NOTIMPLEMENTED(); +} + +void AddNativePostprocessingMixer(ColorProvider* provider) {} + +} // namespace ui diff --git a/chromium/ui/color/linux/native_color_mixers.cc b/chromium/ui/color/linux/native_color_mixers.cc index 2ea973bff1f..e8a68f69376 100644 --- a/chromium/ui/color/linux/native_color_mixers.cc +++ b/chromium/ui/color/linux/native_color_mixers.cc @@ -8,12 +8,18 @@ namespace ui { -void AddNativeCoreColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { NOTIMPLEMENTED(); } -void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { NOTIMPLEMENTED(); } +void AddNativePostprocessingMixer(ColorProvider* provider) {} + } // namespace ui diff --git a/chromium/ui/color/mac/native_color_mixers.mm b/chromium/ui/color/mac/native_color_mixers.mm index 4a769515c0a..4475e0cb57f 100644 --- a/chromium/ui/color/mac/native_color_mixers.mm +++ b/chromium/ui/color/mac/native_color_mixers.mm @@ -5,7 +5,10 @@ #include "ui/color/color_mixers.h" #import + +#include "base/containers/fixed_flat_set.h" #import "skia/ext/skia_utils_mac.h" +#include "ui/color/color_id.h" #include "ui/color/color_mixer.h" #include "ui/color/color_provider.h" #include "ui/color/color_recipe.h" @@ -13,42 +16,56 @@ #include "ui/color/mac/scoped_current_nsappearance.h" #include "ui/gfx/color_palette.h" +namespace { +// All the native OS colors which are retrieved from the system directly. +// clang-format off +constexpr auto kNativeOSColorIds = base::MakeFixedFlatSet({ + ui::kColorFocusableBorderFocused, + ui::kColorLabelSelectionBackground, + ui::kColorMenuBorder, + ui::kColorMenuItemForegroundDisabled, + ui::kColorMenuItemForeground, + ui::kColorMenuSeparator, + ui::kColorTableBackgroundAlternate, + ui::kColorTableGroupingIndicator, + ui::kColorTextfieldSelectionBackground}); +// clang-format on +} + namespace ui { -void AddNativeCoreColorMixer(ColorProvider* provider, bool dark_window) { - ScopedCurrentNSAppearance scoped_nsappearance(dark_window); +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { + ScopedCurrentNSAppearance scoped_nsappearance(dark_window, high_contrast); ColorMixer& mixer = provider->AddMixer(); mixer.AddSet({kColorSetNative, { + {kColorItemHighlight, + SkColorSetA(skia::NSSystemColorToSkColor( + [NSColor keyboardFocusIndicatorColor]), + 0x66)}, {kColorTextSelectionBackground, skia::NSSystemColorToSkColor( [NSColor selectedTextBackgroundColor])}, }}); } -void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window) { - ScopedCurrentNSAppearance scoped_nsappearance(dark_window); +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { + ScopedCurrentNSAppearance scoped_nsappearance(dark_window, high_contrast); ColorMixer& mixer = provider->AddMixer(); mixer.AddSet( {kColorSetNative, { - {kColorFocusableBorderFocused, - SkColorSetA(skia::NSSystemColorToSkColor( - [NSColor keyboardFocusIndicatorColor]), - 0x66)}, {kColorMenuBorder, SkColorSetA(SK_ColorBLACK, 0x60)}, {kColorMenuItemForegroundDisabled, skia::NSSystemColorToSkColor([NSColor disabledControlTextColor])}, {kColorMenuItemForeground, skia::NSSystemColorToSkColor([NSColor controlTextColor])}, - {kColorTextSelectionBackground, - skia::NSSystemColorToSkColor( - [NSColor selectedTextBackgroundColor])}, }}); - mixer[kColorMenuItemForegroundHighlighted] = {kColorPrimaryForeground}; - mixer[kColorMenuItemForegroundSelected] = {kColorPrimaryForeground}; - if (@available(macOS 10.14, *)) { mixer[kColorTableBackgroundAlternate] = {skia::NSSystemColorToSkColor( NSColor.alternatingContentBackgroundColors[1])}; @@ -61,6 +78,27 @@ void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window) { ? SkColorSetA(gfx::kGoogleGrey800, 0xCC) : SkColorSetA(SK_ColorBLACK, 0x26); mixer[kColorMenuSeparator] = {menu_separator_color}; + + if (!high_contrast) + return; + + if (dark_window) { + mixer[kColorMenuItemForegroundSelected] = {SK_ColorBLACK}; + mixer[kColorMenuItemBackgroundSelected] = {SK_ColorLTGRAY}; + } else { + mixer[kColorMenuItemForegroundSelected] = {SK_ColorWHITE}; + mixer[kColorMenuItemBackgroundSelected] = {SK_ColorDKGRAY}; + } +} + +void AddNativePostprocessingMixer(ColorProvider* provider) { + ColorMixer& mixer = provider->AddPostprocessingMixer(); + + for (ColorId id = kUiColorsStart; id < kUiColorsEnd; ++id) { + // Apply system tint to non-OS colors. + if (!kNativeOSColorIds.contains(id)) + mixer[id] += ApplySystemControlTintIfNeeded(); + } } } // namespace ui diff --git a/chromium/ui/color/mac/native_color_transform.mm b/chromium/ui/color/mac/native_color_transform.mm new file mode 100644 index 00000000000..af1c7704402 --- /dev/null +++ b/chromium/ui/color/mac/native_color_transform.mm @@ -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. + +#include "ui/color/color_transform.h" + +#import + +#include "third_party/skia/include/core/SkColor.h" +#include "ui/color/color_id.h" +#include "ui/color/color_mixer.h" +#include "ui/color/mac/system_color_utils.h" +#include "ui/gfx/color_utils.h" + +namespace ui { + +ColorTransform ApplySystemControlTintIfNeeded() { + return base::BindRepeating( + [](SkColor input_color, const ui::ColorMixer& mixer) -> SkColor { + return IsSystemGraphiteTinted() ? ColorToGrayscale(input_color) + : input_color; + }); +} + +} // namespace ui diff --git a/chromium/ui/color/mac/scoped_current_nsappearance.h b/chromium/ui/color/mac/scoped_current_nsappearance.h index 7b134c1e68c..73e8901c000 100644 --- a/chromium/ui/color/mac/scoped_current_nsappearance.h +++ b/chromium/ui/color/mac/scoped_current_nsappearance.h @@ -13,7 +13,7 @@ namespace ui { // based on the desired light/dark colors scheme. class COMPONENT_EXPORT(COLOR) ScopedCurrentNSAppearance { public: - explicit ScopedCurrentNSAppearance(bool dark); + explicit ScopedCurrentNSAppearance(bool dark, bool high_contrast); // There should be no reason to copy or move a ScopedCurrentNSAppearance. ScopedCurrentNSAppearance(const ScopedCurrentNSAppearance&) = delete; diff --git a/chromium/ui/color/mac/scoped_current_nsappearance.mm b/chromium/ui/color/mac/scoped_current_nsappearance.mm index 62bfad44801..35040b01e15 100644 --- a/chromium/ui/color/mac/scoped_current_nsappearance.mm +++ b/chromium/ui/color/mac/scoped_current_nsappearance.mm @@ -7,10 +7,20 @@ #import namespace ui { -ScopedCurrentNSAppearance::ScopedCurrentNSAppearance(bool dark) { +ScopedCurrentNSAppearance::ScopedCurrentNSAppearance(bool dark, + bool high_contrast) { if (@available(macOS 10.14, *)) { - NSAppearanceName appearance = - dark ? NSAppearanceNameDarkAqua : NSAppearanceNameAqua; + NSAppearanceName appearance; + + if (dark) { + appearance = high_contrast + ? NSAppearanceNameAccessibilityHighContrastDarkAqua + : NSAppearanceNameDarkAqua; + } else { + appearance = high_contrast ? NSAppearanceNameAccessibilityHighContrastAqua + : NSAppearanceNameAqua; + } + [NSAppearance setCurrentAppearance:[NSAppearance appearanceNamed:appearance]]; } diff --git a/chromium/ui/color/mac/system_color_utils.h b/chromium/ui/color/mac/system_color_utils.h new file mode 100644 index 00000000000..3705828810f --- /dev/null +++ b/chromium/ui/color/mac/system_color_utils.h @@ -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. + +#ifndef UI_COLOR_MAC_SYSTEM_COLOR_UTILS_H_ +#define UI_COLOR_MAC_SYSTEM_COLOR_UTILS_H_ + +#include "base/component_export.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace ui { + +COMPONENT_EXPORT(COLOR) bool IsSystemGraphiteTinted(); + +COMPONENT_EXPORT(COLOR) SkColor ColorToGrayscale(SkColor color); + +class COMPONENT_EXPORT(COLOR) ScopedEnableGraphiteTint { + public: + ScopedEnableGraphiteTint(); + ScopedEnableGraphiteTint(const ScopedEnableGraphiteTint&) = delete; + ScopedEnableGraphiteTint& operator=(const ScopedEnableGraphiteTint&) = delete; + ~ScopedEnableGraphiteTint(); + + private: + bool original_test_override_ = false; +}; + +} // namespace ui + +#endif // UI_COLOR_MAC_SYSTEM_COLOR_UTILS_H_ diff --git a/chromium/ui/color/mac/system_color_utils.mm b/chromium/ui/color/mac/system_color_utils.mm new file mode 100644 index 00000000000..6b9c6e6a49f --- /dev/null +++ b/chromium/ui/color/mac/system_color_utils.mm @@ -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/color/mac/system_color_utils.h" + +#import + +#include "ui/gfx/color_utils.h" + +namespace { +bool graphite_tint_test_override = false; +} + +namespace ui { + +bool IsSystemGraphiteTinted() { + if (graphite_tint_test_override) + return true; + + return [NSColor currentControlTint] == NSGraphiteControlTint; +} + +SkColor ColorToGrayscale(SkColor color) { + uint8_t component = color_utils::GetLuma(color); + return SkColorSetARGB(SkColorGetA(color), component, component, component); +} + +ScopedEnableGraphiteTint::ScopedEnableGraphiteTint() { + original_test_override_ = graphite_tint_test_override; + graphite_tint_test_override = true; +} + +ScopedEnableGraphiteTint::~ScopedEnableGraphiteTint() { + graphite_tint_test_override = original_test_override_; +} + +} // ui diff --git a/chromium/ui/color/ui_color_mixer.cc b/chromium/ui/color/ui_color_mixer.cc index ecf814bb893..a9c3b72ff6a 100644 --- a/chromium/ui/color/ui_color_mixer.cc +++ b/chromium/ui/color/ui_color_mixer.cc @@ -12,90 +12,164 @@ namespace ui { -void AddUiColorMixer(ColorProvider* provider) { +void AddUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { ColorMixer& mixer = provider->AddMixer(); - const auto button_disabled_background = - BlendForMinContrastWithSelf(kColorButtonBackground, 1.2f); - mixer[kColorAvatarHeaderArt] = {kColorMidground}; mixer[kColorAvatarIconGuest] = {kColorSecondaryForeground}; mixer[kColorAvatarIconIncognito] = {kColorPrimaryForeground}; mixer[kColorBubbleBackground] = {kColorPrimaryBackground}; + mixer[kColorBubbleBorder] = {kColorMidground}; mixer[kColorBubbleFooterBackground] = {kColorSubtleEmphasisBackground}; + mixer[kColorBubbleFooterBorder] = {kColorMidground}; mixer[kColorButtonBackground] = {kColorPrimaryBackground}; - mixer[kColorButtonBorder] = {kColorMidground}; - mixer[kColorButtonBorderDisabled] = button_disabled_background; - mixer[kColorButtonForegroundDisabled] = {kColorDisabledForeground}; - mixer[kColorButtonForeground] = {kColorAccent}; mixer[kColorButtonBackgroundPressed] = {kColorButtonBackground}; mixer[kColorButtonBackgroundProminent] = {kColorAccent}; - mixer[kColorButtonBackgroundProminentDisabled] = button_disabled_background; - mixer[kColorButtonBackgroundProminentFocused] = - BlendForMinContrastWithSelf(kColorButtonBackgroundProminent, 1.3f); + mixer[kColorButtonBackgroundProminentDisabled] = { + kColorSubtleEmphasisBackground}; + mixer[kColorButtonBackgroundProminentFocused] = { + kColorButtonBackgroundProminent}; + mixer[kColorButtonBorder] = {kColorMidground}; + mixer[kColorButtonBorderDisabled] = {kColorSubtleEmphasisBackground}; + mixer[kColorButtonForeground] = {kColorAccent}; + mixer[kColorButtonForegroundChecked] = {kColorButtonForeground}; + mixer[kColorButtonForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorButtonForegroundProminent] = GetColorWithMaxContrast(kColorButtonBackgroundProminent); mixer[kColorButtonForegroundUnchecked] = {kColorSecondaryForeground}; mixer[kColorDialogBackground] = {kColorPrimaryBackground}; mixer[kColorDialogForeground] = {kColorSecondaryForeground}; - mixer[kColorFocusableBorderFocused] = SetAlpha(kColorAccent, 0x4D); + mixer[kColorDropdownBackground] = {kColorPrimaryBackground}; + mixer[kColorDropdownBackgroundSelected] = {kColorMenuSelectionBackground}; + mixer[kColorDropdownForeground] = {kColorPrimaryForeground}; + mixer[kColorDropdownForegroundSelected] = {kColorPrimaryForeground}; + mixer[kColorFocusableBorderFocused] = {kColorItemHighlight}; mixer[kColorFocusableBorderUnfocused] = {kColorMidground}; + mixer[kColorFrameActive] = {dark_window ? gfx::kGoogleGrey900 + : SkColorSetRGB(0xDE, 0xE1, 0xE6)}; + mixer[kColorFrameInactive] = {dark_window ? gfx::kGoogleGrey800 + : gfx::kGoogleGrey200}; + mixer[kColorHelpIconActive] = {kColorPrimaryForeground}; + mixer[kColorHelpIconInactive] = {kColorSecondaryForeground}; mixer[kColorIcon] = {kColorSecondaryForeground}; - mixer[kColorMenuIcon] = {kColorIcon}; - mixer[kColorLabelForegroundDisabled] = {kColorDisabledForeground}; + mixer[kColorIconDisabled] = SetAlpha(kColorIcon, gfx::kDisabledControlAlpha); mixer[kColorLabelForeground] = {kColorPrimaryForeground}; + mixer[kColorLabelForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorLabelForegroundSecondary] = {kColorSecondaryForeground}; mixer[kColorLabelSelectionBackground] = {kColorTextSelectionBackground}; - mixer[kColorLabelSelectionForeground] = {kColorLabelForeground}; + mixer[kColorLabelSelectionForeground] = {kColorTextSelectionForeground}; + mixer[kColorLinkForeground] = {kColorAccent}; mixer[kColorLinkForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorLinkForegroundPressed] = {kColorLinkForeground}; - mixer[kColorLinkForeground] = {kColorAccent}; mixer[kColorMenuBackground] = {kColorPrimaryBackground}; mixer[kColorMenuBorder] = {kColorMidground}; + mixer[kColorMenuDropmarker] = {kColorPrimaryForeground}; + mixer[kColorMenuIcon] = {kColorIcon}; mixer[kColorMenuItemBackgroundAlertedInitial] = SetAlpha(kColorAccent, 0x4D); - mixer[kColorMenuItemBackgroundAlertedTarget] = SetAlpha(kColorAccent, 0x1A); - mixer[kColorMenuItemForegroundDisabled] = {kColorDisabledForeground}; - mixer[kColorMenuItemForeground] = {kColorPrimaryForeground}; + mixer[kColorMenuItemBackgroundAlertedTarget] = + SetAlpha(kColorAccent, gfx::kGoogleGreyAlpha200); mixer[kColorMenuItemBackgroundHighlighted] = {kColorSubtleEmphasisBackground}; + mixer[kColorMenuItemBackgroundSelected] = {kColorMenuSelectionBackground}; + mixer[kColorMenuItemForeground] = {kColorPrimaryForeground}; + mixer[kColorMenuItemForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorMenuItemForegroundHighlighted] = {kColorMenuItemForeground}; mixer[kColorMenuItemForegroundSecondary] = {kColorSecondaryForeground}; - mixer[kColorMenuItemBackgroundSelected] = {kColorItemSelectionBackground}; mixer[kColorMenuItemForegroundSelected] = {kColorMenuItemForeground}; mixer[kColorMenuSeparator] = {kColorMidground}; + mixer[kColorNotificationActionsBackground] = { + kColorNotificationBackgroundActive}; + mixer[kColorNotificationBackgroundActive] = {kColorSubtleEmphasisBackground}; + mixer[kColorNotificationBackgroundInactive] = {kColorPrimaryBackground}; + mixer[kColorNotificationHeaderForeground] = {kColorSecondaryForeground}; + mixer[kColorNotificationIconBackground] = { + kColorNotificationHeaderForeground}; + mixer[kColorNotificationIconForeground] = { + kColorNotificationBackgroundInactive}; + mixer[kColorNotificationImageBackground] = { + kColorNotificationBackgroundActive}; + mixer[kColorNotificationInputBackground] = {kColorAccent}; + mixer[kColorNotificationInputForeground] = + GetColorWithMaxContrast(kColorNotificationInputBackground); + mixer[kColorNotificationInputPlaceholderForeground] = + SetAlpha(kColorNotificationInputForeground, gfx::kGoogleGreyAlpha700); + mixer[kColorOverlayScrollbarFill] = + SetAlpha(kColorEndpointForeground, gfx::kGoogleGreyAlpha700); + mixer[kColorOverlayScrollbarFillHovered] = + SetAlpha(kColorEndpointForeground, gfx::kGoogleGreyAlpha800); + mixer[kColorOverlayScrollbarStroke] = + SetAlpha(kColorEndpointBackground, gfx::kGoogleGreyAlpha400); + mixer[kColorOverlayScrollbarStrokeHovered] = + SetAlpha(kColorEndpointBackground, gfx::kGoogleGreyAlpha500); + mixer[kColorPwaSecurityChipForeground] = {kColorSecondaryForeground}; + mixer[kColorPwaSecurityChipForegroundDangerous] = {kColorAlertHighSeverity}; + mixer[kColorPwaSecurityChipForegroundPolicyCert] = {kColorDisabledForeground}; + mixer[kColorPwaSecurityChipForegroundSecure] = { + kColorPwaSecurityChipForeground}; + mixer[kColorPwaToolbarBackground] = {kColorEndpointBackground}; + mixer[kColorPwaToolbarForeground] = {kColorEndpointForeground}; + mixer[kColorSeparator] = {kColorMidground}; + mixer[kColorSliderThumb] = {kColorAccent}; + mixer[kColorSliderThumbMinimal] = {kColorSecondaryForeground}; + mixer[kColorSliderTrack] = {kColorSubtleAccent}; + mixer[kColorSliderTrackMinimal] = {kColorMidground}; + mixer[kColorSyncInfoBackground] = {kColorSubtleEmphasisBackground}; + mixer[kColorSyncInfoBackgroundError] = + SetAlpha(kColorAlertHighSeverity, gfx::kGoogleGreyAlpha100); + mixer[kColorSyncInfoBackgroundPaused] = + SetAlpha(kColorAccent, gfx::kGoogleGreyAlpha100); + mixer[kColorTabBackgroundHighlighted] = SetAlpha(gfx::kGoogleBlue300, 0x2B); + mixer[kColorTabBackgroundHighlightedFocused] = + SetAlpha(gfx::kGoogleBlue300, 0x53); + mixer[kColorTabBorderSelected] = {kColorAccent}; mixer[kColorTabContentSeparator] = {kColorMidground}; mixer[kColorTabForeground] = {kColorSecondaryForeground}; - mixer[kColorTabBorderSelected] = {kColorAccent}; mixer[kColorTabForegroundSelected] = {kColorAccent}; mixer[kColorTableBackground] = {kColorPrimaryBackground}; - mixer[kColorTableForeground] = {kColorPrimaryForeground}; - mixer[kColorTableGroupingIndicator] = {kColorTableBackgroundSelectedFocused}; - mixer[kColorTableHeaderBackground] = {kColorTableBackground}; - mixer[kColorTableHeaderForeground] = {kColorTableForeground}; - mixer[kColorTableHeaderSeparator] = {kColorMidground}; + mixer[kColorTableBackgroundAlternate] = {kColorTableBackground}; mixer[kColorTableBackgroundSelectedFocused] = {kColorItemSelectionBackground}; - mixer[kColorTableForegroundSelectedFocused] = {kColorTableForeground}; mixer[kColorTableBackgroundSelectedUnfocused] = { kColorTableBackgroundSelectedFocused}; + mixer[kColorTableForeground] = {kColorPrimaryForeground}; + mixer[kColorTableForegroundSelectedFocused] = {kColorTableForeground}; mixer[kColorTableForegroundSelectedUnfocused] = { kColorTableForegroundSelectedFocused}; - mixer[kColorTextfieldBackground] = - GetColorWithMaxContrast(kColorTextfieldForeground); + mixer[kColorTableGroupingIndicator] = {kColorItemHighlight}; + mixer[kColorTableHeaderBackground] = {kColorTableBackground}; + mixer[kColorTableHeaderForeground] = {kColorTableForeground}; + mixer[kColorTableHeaderSeparator] = {kColorMidground}; + mixer[kColorTextfieldBackground] = {kColorEndpointBackground}; mixer[kColorTextfieldBackgroundDisabled] = {kColorPrimaryBackground}; + mixer[kColorTextfieldForeground] = {kColorPrimaryForeground}; mixer[kColorTextfieldForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorTextfieldForegroundPlaceholder] = { kColorTextfieldForegroundDisabled}; - mixer[kColorTextfieldForeground] = {kColorPrimaryForeground}; mixer[kColorTextfieldSelectionBackground] = {kColorTextSelectionBackground}; - mixer[kColorTextfieldSelectionForeground] = {kColorTextfieldForeground}; + mixer[kColorTextfieldSelectionForeground] = {kColorTextSelectionForeground}; mixer[kColorThrobber] = {kColorAccent}; + mixer[kColorThrobberPreconnect] = {kColorSubtleAccent}; + mixer[kColorToggleButtonShadow] = {kColorMidground}; + mixer[kColorToggleButtonThumbOff] = {kColorSecondaryForeground}; + mixer[kColorToggleButtonThumbOn] = {kColorAccent}; + if (dark_window) { + mixer[kColorToggleButtonThumbOff] += + AlphaBlend(kColorPrimaryForeground, FromTransformInput(), 0x0D); + mixer[kColorToggleButtonThumbOn] += + AlphaBlend(kColorPrimaryForeground, FromTransformInput(), 0x0D); + } + mixer[kColorToggleButtonTrackOff] = { + dark_window ? ColorTransform(gfx::kGoogleGrey700) : kColorMidground}; + mixer[kColorToggleButtonTrackOn] = {dark_window ? gfx::kGoogleBlue600 + : gfx::kGoogleBlue300}; mixer[kColorTooltipBackground] = SetAlpha(kColorPrimaryBackground, 0xCC); mixer[kColorTooltipForeground] = SetAlpha(kColorPrimaryForeground, 0xDE); mixer[kColorTreeBackground] = {kColorPrimaryBackground}; - mixer[kColorTreeNodeForeground] = {kColorPrimaryForeground}; mixer[kColorTreeNodeBackgroundSelectedFocused] = { kColorItemSelectionBackground}; - mixer[kColorTreeNodeForegroundSelectedFocused] = {kColorTreeNodeForeground}; mixer[kColorTreeNodeBackgroundSelectedUnfocused] = { kColorTreeNodeBackgroundSelectedFocused}; + mixer[kColorTreeNodeForeground] = {kColorPrimaryForeground}; + mixer[kColorTreeNodeForegroundSelectedFocused] = {kColorTreeNodeForeground}; mixer[kColorTreeNodeForegroundSelectedUnfocused] = { kColorTreeNodeForegroundSelectedFocused}; mixer[kColorWindowBackground] = {kColorPrimaryBackground}; diff --git a/chromium/ui/color/win/native_color_mixers.cc b/chromium/ui/color/win/native_color_mixers.cc index 75b9326f5ac..9f6ba502624 100644 --- a/chromium/ui/color/win/native_color_mixers.cc +++ b/chromium/ui/color/win/native_color_mixers.cc @@ -9,57 +9,137 @@ #include "ui/color/color_id.h" #include "ui/color/color_mixer.h" #include "ui/color/color_provider.h" +#include "ui/color/color_recipe.h" #include "ui/color/color_set.h" +#include "ui/color/color_transform.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" namespace ui { -void AddNativeCoreColorMixer(ColorProvider* provider, bool dark_window) { +void AddNativeCoreColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { // TODO(pkasting): Not clear whether this is really the set of interest. // Maybe there's some way to query colors used by UxTheme.dll, or maybe we // should be hardcoding a list of colors for system light/dark modes based on // reverse-engineering current Windows behavior. Or maybe the union of all // these. -#define MAP(chrome, native) {chrome, color_utils::GetSysSkColor(native)} - provider->AddMixer().AddSet( - {kColorSetNative, - { - MAP(kColorNative3dDkShadow, COLOR_3DDKSHADOW), - MAP(kColorNative3dLight, COLOR_3DLIGHT), - MAP(kColorNativeActiveBorder, COLOR_ACTIVEBORDER), - MAP(kColorNativeActiveCaption, COLOR_ACTIVECAPTION), - MAP(kColorNativeAppWorkspace, COLOR_APPWORKSPACE), - MAP(kColorNativeBackground, COLOR_BACKGROUND), - MAP(kColorNativeBtnFace, COLOR_BTNFACE), - MAP(kColorNativeBtnHighlight, COLOR_BTNHIGHLIGHT), - MAP(kColorNativeBtnShadow, COLOR_BTNSHADOW), - MAP(kColorNativeBtnText, COLOR_BTNTEXT), - MAP(kColorNativeCaptionText, COLOR_CAPTIONTEXT), - MAP(kColorNativeGradientActiveCaption, COLOR_GRADIENTACTIVECAPTION), - MAP(kColorNativeGradientInactiveCaption, - COLOR_GRADIENTINACTIVECAPTION), - MAP(kColorNativeGrayText, COLOR_GRAYTEXT), - MAP(kColorNativeHighlight, COLOR_HIGHLIGHT), - MAP(kColorNativeHighlightText, COLOR_HIGHLIGHTTEXT), - MAP(kColorNativeHotlight, COLOR_HOTLIGHT), - MAP(kColorNativeInactiveBorder, COLOR_INACTIVEBORDER), - MAP(kColorNativeInactiveCaption, COLOR_INACTIVECAPTION), - MAP(kColorNativeInactiveCaptionText, COLOR_INACTIVECAPTIONTEXT), - MAP(kColorNativeInfoBk, COLOR_INFOBK), - MAP(kColorNativeInfoText, COLOR_INFOTEXT), - MAP(kColorNativeMenu, COLOR_MENU), - MAP(kColorNativeMenuBar, COLOR_MENUBAR), - MAP(kColorNativeMenuHilight, COLOR_MENUHILIGHT), - MAP(kColorNativeMenuText, COLOR_MENUTEXT), - MAP(kColorNativeScrollbar, COLOR_SCROLLBAR), - MAP(kColorNativeWindow, COLOR_WINDOW), - MAP(kColorNativeWindowFrame, COLOR_WINDOWFRAME), - MAP(kColorNativeWindowText, COLOR_WINDOWTEXT), - }}); + ColorMixer& mixer = provider->AddMixer(); + + if (!high_contrast) + return; + +#define E(chrome, native) {chrome, color_utils::GetSysSkColor(native)}, + mixer.AddSet({kColorSetNative, {WIN_COLOR_IDS}}); +#undef E + + // Window Background + mixer[kColorPrimaryBackground] = {kColorNativeWindow}; + + // Window Text + mixer[kColorAlertLowSeverity] = {kColorNativeWindowText}; + mixer[kColorAlertMediumSeverity] = {kColorNativeWindowText}; + mixer[kColorAlertHighSeverity] = {kColorNativeWindowText}; + mixer[kColorIcon] = {kColorNativeWindowText}; + mixer[kColorMidground] = {kColorNativeWindowText}; + mixer[kColorPrimaryForeground] = {kColorNativeWindowText}; + mixer[kColorSecondaryForeground] = {kColorNativeWindowText}; + + // Gray/Disabled Text + mixer[kColorDisabledForeground] = {kColorNativeGrayText}; + + // Button Background + mixer[kColorSubtleEmphasisBackground] = {kColorNativeBtnFace}; + + // Button Text Foreground + mixer[kColorMenuItemForeground] = {kColorNativeBtnText}; + + // Highlight/Selected Background + mixer[kColorAccent] = {kColorNativeHighlight}; + mixer[kColorItemSelectionBackground] = {kColorNativeHighlight}; + mixer[kColorMenuSelectionBackground] = {kColorNativeHighlight}; + mixer[kColorSubtleAccent] = {kColorNativeHighlight}; + mixer[kColorTextSelectionBackground] = {kColorNativeHighlight}; + + // Highlight/Selected Text Foreground + mixer[kColorTextSelectionForeground] = {kColorNativeHighlightText}; } -void AddNativeUiColorMixer(ColorProvider* provider, bool dark_window) { - // TODO(pkasting): Add recipes +void AddNativeUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { + if (!high_contrast) + return; + + ColorMixer& mixer = provider->AddMixer(); + + mixer[kColorButtonForegroundChecked] = {dark_window ? gfx::kGoogleBlue100 + : gfx::kGoogleBlue900}; + mixer[kColorNotificationInputPlaceholderForeground] = + SetAlpha(kColorNotificationInputForeground, gfx::kGoogleGreyAlpha700); + mixer[kColorSliderTrack] = AlphaBlend( + kColorNativeHighlight, kColorNativeWindow, gfx::kGoogleGreyAlpha400); + + // Window Background + mixer[kColorBubbleFooterBackground] = {kColorNativeWindow}; + mixer[kColorTooltipBackground] = {kColorNativeWindow}; + mixer[kColorButtonBackgroundProminentDisabled] = {kColorNativeWindow}; + + // Window Text + mixer[kColorTableGroupingIndicator] = {kColorNativeWindowText}; + mixer[kColorThrobber] = {kColorNativeWindowText}; + mixer[kColorTooltipForeground] = {kColorNativeWindowText}; + + // Hyperlinks + mixer[kColorLinkForeground] = {kColorNativeHotlight}; + mixer[kColorLinkForegroundPressed] = {kColorNativeHotlight}; + mixer[kColorMenuItemForegroundHighlighted] = {kColorNativeHotlight}; + + // Gray/Disabled Text + mixer[kColorMenuItemForegroundDisabled] = {kColorNativeGrayText}; + mixer[kColorLinkForegroundDisabled] = {kColorNativeGrayText}; + mixer[kColorLabelForegroundDisabled] = {kColorNativeGrayText}; + mixer[kColorButtonForegroundDisabled] = {kColorNativeGrayText}; + mixer[kColorThrobberPreconnect] = {kColorNativeGrayText}; + + // Button Background + mixer[kColorButtonBackground] = {kColorNativeBtnFace}; + mixer[kColorMenuBackground] = {kColorNativeBtnFace}; + mixer[kColorTextfieldBackground] = {kColorNativeBtnFace}; + mixer[kColorTextfieldBackgroundDisabled] = {kColorNativeBtnFace}; + + // Button Text Foreground + mixer[kColorButtonForeground] = {kColorNativeBtnText}; + mixer[kColorFocusableBorderFocused] = {kColorNativeBtnText}; + mixer[kColorFocusableBorderUnfocused] = {kColorNativeBtnText}; + mixer[kColorMenuBorder] = {kColorNativeBtnText}; + mixer[kColorMenuItemForegroundSecondary] = {kColorNativeBtnText}; + mixer[kColorMenuSeparator] = {kColorNativeBtnText}; + mixer[kColorSeparator] = {kColorNativeBtnText}; + mixer[kColorTabContentSeparator] = {kColorNativeBtnText}; + mixer[kColorTabForeground] = {kColorNativeBtnText}; + mixer[kColorTabForegroundSelected] = {kColorNativeBtnText}; + mixer[kColorTextfieldForeground] = {kColorNativeBtnText}; + mixer[kColorTextfieldForegroundPlaceholder] = {kColorNativeBtnText}; + mixer[kColorTextfieldForegroundDisabled] = {kColorNativeBtnText}; + + // Highlight/Selected Background + mixer[kColorButtonBorder] = {kColorNativeHighlight}; + mixer[kColorButtonBackgroundProminentFocused] = {kColorNativeHighlight}; + mixer[kColorHelpIconActive] = {kColorNativeHighlight}; + + // Highlight/Selected Text Foreground + mixer[kColorButtonForegroundProminent] = {kColorNativeHighlightText}; + mixer[kColorMenuItemForegroundSelected] = {kColorNativeHighlightText}; + mixer[kColorNotificationInputForeground] = {kColorNativeHighlightText}; + mixer[kColorTableForegroundSelectedFocused] = {kColorNativeHighlightText}; + mixer[kColorTableForegroundSelectedUnfocused] = {kColorNativeHighlightText}; + mixer[kColorTreeNodeForegroundSelectedFocused] = {kColorNativeHighlightText}; + mixer[kColorTreeNodeForegroundSelectedUnfocused] = { + kColorNativeHighlightText}; } +void AddNativePostprocessingMixer(ColorProvider* provider) {} + } // namespace ui diff --git a/chromium/ui/compositor/BUILD.gn b/chromium/ui/compositor/BUILD.gn index 75b4168ede8..ea8c813108d 100644 --- a/chromium/ui/compositor/BUILD.gn +++ b/chromium/ui/compositor/BUILD.gn @@ -275,4 +275,13 @@ test("compositor_unittests") { if (is_linux || is_chromeos) { deps += [ "//third_party/mesa_headers" ] } + + if (is_fuchsia) { + additional_manifest_fragments = [ + # TODO(crbug.com/1185811): Figure out why jit_capabilities is needed. + "//build/config/fuchsia/test/jit_capabilities.test-cmx", + + "//build/config/fuchsia/test/present_view_capabilities.test-cmx", + ] + } } diff --git a/chromium/ui/compositor/OWNERS b/chromium/ui/compositor/OWNERS index 3807753ca24..012d9456785 100644 --- a/chromium/ui/compositor/OWNERS +++ b/chromium/ui/compositor/OWNERS @@ -1,4 +1,3 @@ -danakj@chromium.org enne@chromium.org flackr@chromium.org kylechar@chromium.org diff --git a/chromium/ui/compositor/compositor.cc b/chromium/ui/compositor/compositor.cc index 8272ff517f1..34f84bbdc2c 100644 --- a/chromium/ui/compositor/compositor.cc +++ b/chromium/ui/compositor/compositor.cc @@ -5,7 +5,9 @@ #include "ui/compositor/compositor.h" #include + #include +#include #include #include @@ -246,7 +248,8 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id, if (base::FeatureList::IsEnabled(features::kUiCompositorScrollWithLayers) && compositor_delegate) { input_handler_weak_ = cc::InputHandler::Create(*compositor_delegate); - scroll_input_handler_.reset(new ScrollInputHandler(input_handler_weak_)); + scroll_input_handler_ = + std::make_unique(input_handler_weak_); } animation_timeline_ = @@ -750,7 +753,11 @@ void Compositor::StartThroughputTracker( } void Compositor::StopThroughtputTracker(TrackerId tracker_id) { - DCHECK(base::Contains(throughput_tracker_map_, 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)); animation_host_->StopThroughputTracking(tracker_id); } diff --git a/chromium/ui/compositor/layer_unittest.cc b/chromium/ui/compositor/layer_unittest.cc index 4f2d5240c4a..fb1e5fd34f4 100644 --- a/chromium/ui/compositor/layer_unittest.cc +++ b/chromium/ui/compositor/layer_unittest.cc @@ -221,10 +221,13 @@ class LayerWithRealCompositorTest : public testing::TestWithParam { ReadbackHolder() : run_loop_(std::make_unique()) {} void OutputRequestCallback(std::unique_ptr result) { - if (result->IsEmpty()) + if (result->IsEmpty()) { result_.reset(); - else - result_ = std::make_unique(result->AsSkBitmap()); + } else { + auto scoped_bitmap = result->ScopedAccessSkBitmap(); + result_ = + std::make_unique(scoped_bitmap.GetOutScopedBitmap()); + } run_loop_->Quit(); } diff --git a/chromium/ui/compositor/test/test_compositor_host_ozone.cc b/chromium/ui/compositor/test/test_compositor_host_ozone.cc index 9ebb06b5da0..ac0cbf92b78 100644 --- a/chromium/ui/compositor/test/test_compositor_host_ozone.cc +++ b/chromium/ui/compositor/test/test_compositor_host_ozone.cc @@ -36,7 +36,7 @@ class TestCompositorHostOzone::StubPlatformWindowDelegate gfx::AcceleratedWidget widget() const { return widget_; } // PlatformWindowDelegate: - void OnBoundsChanged(const gfx::Rect& new_bounds) override {} + void OnBoundsChanged(const BoundsChange& change) override {} void OnDamageRect(const gfx::Rect& damaged_region) override {} void DispatchEvent(Event* event) override {} void OnCloseRequest() override {} diff --git a/chromium/ui/compositor/total_animation_throughput_reporter.cc b/chromium/ui/compositor/total_animation_throughput_reporter.cc index 7f9e80126dd..90fbdce307b 100644 --- a/chromium/ui/compositor/total_animation_throughput_reporter.cc +++ b/chromium/ui/compositor/total_animation_throughput_reporter.cc @@ -44,6 +44,9 @@ void TotalAnimationThroughputReporter::OnLastAnimationEnded( ui::Compositor* compositor) { throughput_tracker_->Stop(); throughput_tracker_.reset(); + // Stop observing if no need to report multiple times. + if (report_repeating_callback_.is_null()) + compositor_->RemoveObserver(this); } void TotalAnimationThroughputReporter::OnCompositingShuttingDown( diff --git a/chromium/ui/compositor/total_animation_throughput_reporter_unittest.cc b/chromium/ui/compositor/total_animation_throughput_reporter_unittest.cc index e62fba30182..f801150e03e 100644 --- a/chromium/ui/compositor/total_animation_throughput_reporter_unittest.cc +++ b/chromium/ui/compositor/total_animation_throughput_reporter_unittest.cc @@ -11,6 +11,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "cc/metrics/frame_sequence_metrics.h" +#include "ui/compositor/compositor_observer.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/layer_animator.h" @@ -252,6 +253,32 @@ TEST_F(TotalAnimationThroughputReporterTest, PersistedAnimation) { EXPECT_TRUE(checker.WaitUntilReported()); } +namespace { + +class ObserverChecker : public ui::CompositorObserver { + public: + ObserverChecker(ui::Compositor* compositor, + ui::CompositorObserver* reporter_observer) + : reporter_observer_(reporter_observer) { + EXPECT_TRUE(compositor->HasObserver(reporter_observer_)); + compositor->AddObserver(this); + } + ObserverChecker(const ObserverChecker&) = delete; + ObserverChecker& operator=(const ObserverChecker&) = delete; + ~ObserverChecker() override = default; + + // ui::CompositorObserver: + void OnLastAnimationEnded(ui::Compositor* compositor) override { + EXPECT_FALSE(compositor->HasObserver(reporter_observer_)); + compositor->RemoveObserver(this); + } + + private: + ui::CompositorObserver* const reporter_observer_; +}; + +} // namespace + // Make sure the once reporter is called only once. TEST_F(TotalAnimationThroughputReporterTest, OnceReporter) { Layer layer; @@ -267,6 +294,10 @@ TEST_F(TotalAnimationThroughputReporterTest, OnceReporter) { TotalAnimationThroughputReporter reporter( compositor(), checker.once_callback(), /*should_delete=*/false); + // Make sure the TotalAnimationThroughputReporter removes itself + // from compositor as observer. + ObserverChecker observer_checker(compositor(), &reporter); + // Report data for animation of opacity goes to 1. layer.SetOpacity(1.0f); EXPECT_TRUE(checker.WaitUntilReported()); diff --git a/chromium/ui/display/manager/display_manager.h b/chromium/ui/display/manager/display_manager.h index 585980f52ff..b072991fb40 100644 --- a/chromium/ui/display/manager/display_manager.h +++ b/chromium/ui/display/manager/display_manager.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/chromium/ui/display/manager/touch_device_manager.cc b/chromium/ui/display/manager/touch_device_manager.cc index 474c95d5b1c..bd4ecbabd84 100644 --- a/chromium/ui/display/manager/touch_device_manager.cc +++ b/chromium/ui/display/manager/touch_device_manager.cc @@ -29,39 +29,6 @@ using DeviceList = std::vector; constexpr char kFallbackTouchDeviceName[] = "fallback_touch_device_name"; constexpr char kFallbackTouchDevicePhys[] = "fallback_touch_device_phys"; -base::FilePath GetDisplaySysPath(const ManagedDisplayInfo* display) { - std::vector components; - display->sys_path().GetComponents(&components); - base::FilePath path_thus_far; - - for (const auto& component : components) { - if (path_thus_far.empty()) { - path_thus_far = base::FilePath(component); - } else { - path_thus_far = path_thus_far.Append(component); - } - - // Newer versions of the EVDI kernel driver include a symlink to the USB - // device in the sysfs EVDI directory (e.g. - // /sys/devices/platform/evdi.0/device) for EVDI displays that are USB. If - // that symlink exists, read it, and use that path as the sysfs path for the - // display when calculating the association score to match it with a - // corresponding USB touch device. If the symlink doesn't exist, use the - // normal sysfs path. - if (base::StartsWith(component, "evdi", base::CompareCase::SENSITIVE)) { - base::FilePath usb_device_path; - if (base::ReadSymbolicLink(path_thus_far.Append("device"), - &usb_device_path)) { - return base::MakeAbsoluteFilePath( - path_thus_far.Append(usb_device_path)); - } - break; - } - } - - return display->sys_path(); -} - // Returns true if |path| is likely a USB device. bool IsDeviceConnectedViaUsb(const base::FilePath& path) { std::vector components; @@ -89,7 +56,7 @@ int GetUsbAssociationScore(const ManagedDisplayInfo* display, const ui::TouchscreenDevice& device) { // If the devices are not both connected via USB, then there cannot be a USB // association score. - if (!IsDeviceConnectedViaUsb(GetDisplaySysPath(display)) || + if (!IsDeviceConnectedViaUsb(display->sys_path()) || !IsDeviceConnectedViaUsb(device.sys_path)) return 0; @@ -97,7 +64,7 @@ int GetUsbAssociationScore(const ManagedDisplayInfo* display, // sysfs paths have in common. std::vector display_components; std::vector device_components; - GetDisplaySysPath(display).GetComponents(&display_components); + display->sys_path().GetComponents(&display_components); device.sys_path.GetComponents(&device_components); std::size_t largest_idx = 0; @@ -351,8 +318,7 @@ void TouchDeviceManager::AssociateTouchscreens( for (const ManagedDisplayInfo* display : displays) { VLOG(2) << "Received display " << display->name() << " (size: " << display->GetNativeModeSize().ToString() << ", " - << "sys_path: " << GetDisplaySysPath(display).LossyDisplayName() - << ")"; + << "sys_path: " << display->sys_path().LossyDisplayName() << ")"; } for (const ui::TouchscreenDevice& device : devices) { VLOG(2) << "Received device " << device.name diff --git a/chromium/ui/events/BUILD.gn b/chromium/ui/events/BUILD.gn index 5ebdb369a37..767c19f3432 100644 --- a/chromium/ui/events/BUILD.gn +++ b/chromium/ui/events/BUILD.gn @@ -391,7 +391,7 @@ component("events") { if (is_fuchsia) { public += [ "fuchsia/input_event_dispatcher.h", - "fuchsia/input_event_dispatcher_delegate.h", + "fuchsia/input_event_sink.h", ] sources += [ "fuchsia/input_event_dispatcher.cc" ] public_deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input" ] diff --git a/chromium/ui/events/android/drag_event_android.cc b/chromium/ui/events/android/drag_event_android.cc index e5a5e30b69e..f7343f01ebe 100644 --- a/chromium/ui/events/android/drag_event_android.cc +++ b/chromium/ui/events/android/drag_event_android.cc @@ -15,7 +15,7 @@ DragEventAndroid::DragEventAndroid( int action, const gfx::PointF& location, const gfx::PointF& screen_location, - const std::vector& mime_types, + const std::vector& mime_types, jstring content) : action_(action), location_(location), diff --git a/chromium/ui/events/android/drag_event_android.h b/chromium/ui/events/android/drag_event_android.h index 9619ceeda12..a45009be1a4 100644 --- a/chromium/ui/events/android/drag_event_android.h +++ b/chromium/ui/events/android/drag_event_android.h @@ -6,11 +6,11 @@ #define UI_EVENTS_ANDROID_DRAG_EVENT_ANDROID_H_ #include +#include #include #include "base/android/scoped_java_ref.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/events/events_export.h" #include "ui/gfx/geometry/point_conversions.h" @@ -28,14 +28,14 @@ class EVENTS_EXPORT DragEventAndroid { int action, const gfx::PointF& location, const gfx::PointF& screen_location, - const std::vector& mime_types, + const std::vector& mime_types, jstring content); ~DragEventAndroid(); int action() const { return action_; } const gfx::PointF& location_f() const { return location_; } const gfx::PointF& screen_location_f() const { return screen_location_; } - const std::vector& mime_types() const { return mime_types_; } + const std::vector& mime_types() const { return mime_types_; } const gfx::Point GetLocation() const; const gfx::Point GetScreenLocation() const; @@ -52,7 +52,7 @@ class EVENTS_EXPORT DragEventAndroid { gfx::PointF location_; // Location relative to the screen coordinate. gfx::PointF screen_location_; - const std::vector& mime_types_; + const std::vector& mime_types_; // The Java reference to the drop content to avoid unnecessary copying. base::android::ScopedJavaGlobalRef content_; diff --git a/chromium/ui/events/base_event_utils.cc b/chromium/ui/events/base_event_utils.cc index f6a14c100b4..29d057fbb21 100644 --- a/chromium/ui/events/base_event_utils.cc +++ b/chromium/ui/events/base_event_utils.cc @@ -27,11 +27,6 @@ const int kSystemKeyModifierMask = EF_COMMAND_DOWN; const int kSystemKeyModifierMask = EF_ALT_DOWN; #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_APPLE) -bool IsValidTimebase(base::TimeTicks now, base::TimeTicks timestamp) { - int64_t delta = (now - timestamp).InMilliseconds(); - return delta >= 0 && delta <= 60 * 1000; -} - } // namespace base::AtomicSequenceNumber g_next_event_id; @@ -73,6 +68,11 @@ base::TimeTicks EventTimeStampFromSeconds(double time_stamp_seconds) { return base::TimeTicks() + base::TimeDelta::FromSecondsD(time_stamp_seconds); } +bool IsValidTimebase(base::TimeTicks now, base::TimeTicks timestamp) { + int64_t delta = (now - timestamp).InMilliseconds(); + return delta >= 0 && delta <= 60 * 1000; +} + void ValidateEventTimeClock(base::TimeTicks* timestamp) { // Some fraction of devices, across all platforms provide bogus event // timestamps. See https://crbug.com/650338#c1. Correct timestamps which are diff --git a/chromium/ui/events/base_event_utils.h b/chromium/ui/events/base_event_utils.h index 3b5909fd58f..2c5743c11b5 100644 --- a/chromium/ui/events/base_event_utils.h +++ b/chromium/ui/events/base_event_utils.h @@ -43,6 +43,13 @@ EVENTS_BASE_EXPORT double EventTimeStampToSeconds(base::TimeTicks time_stamp); EVENTS_BASE_EXPORT base::TimeTicks EventTimeStampFromSeconds( double time_stamp_seconds); +// Returns false if an event timestamp is clearly bogus given that the event +// was generated a short time before |now|. Some fraction of devices, across +// all platforms provide bogus event timestamps. See +// https://crbug.com/650338#c1. +EVENTS_BASE_EXPORT bool IsValidTimebase(base::TimeTicks now, + base::TimeTicks timestamp); + // Ensures that the event timestamp values are coming from the same underlying // monotonic clock as base::TimeTicks::Now() and if it is not then falls // back to using the current ticks for event timestamp. diff --git a/chromium/ui/events/blink/blink_features.cc b/chromium/ui/events/blink/blink_features.cc index 73a9903412c..806521a65dc 100644 --- a/chromium/ui/events/blink/blink_features.cc +++ b/chromium/ui/events/blink/blink_features.cc @@ -12,4 +12,7 @@ const base::Feature kSendMouseLeaveEvents{"SendMouseLeaveEvents", const base::Feature kDontSendKeyEventsToJavascript{ "DontSendKeyEventsToJavascript", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kReduceHorizontalFlingVelocity{ + "ReduceHorizontalFlingVelocity", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features diff --git a/chromium/ui/events/blink/blink_features.h b/chromium/ui/events/blink/blink_features.h index f1fe50c3f44..ded8eacf804 100644 --- a/chromium/ui/events/blink/blink_features.h +++ b/chromium/ui/events/blink/blink_features.h @@ -22,6 +22,11 @@ extern const base::Feature kSendMouseLeaveEvents; COMPONENT_EXPORT(BLINK_FEATURES) extern const base::Feature kDontSendKeyEventsToJavascript; +// Reduces the velocity of horizontal flings. This is an experiment to test +// a simple means of making flings in mandatory scroll snap areas feel more +// natural. See https://crbug.com/1189696 for details. +COMPONENT_EXPORT(BLINK_FEATURES) +extern const base::Feature kReduceHorizontalFlingVelocity; } #endif // UI_EVENTS_BLINK_BLINK_FEATURES_H_ diff --git a/chromium/ui/events/blink/fling_booster.cc b/chromium/ui/events/blink/fling_booster.cc index d0cd9fb1434..5e5d6c80e97 100644 --- a/chromium/ui/events/blink/fling_booster.cc +++ b/chromium/ui/events/blink/fling_booster.cc @@ -5,6 +5,7 @@ #include "ui/events/blink/fling_booster.h" #include "base/trace_event/trace_event.h" +#include "ui/events/blink/blink_features.h" using blink::WebGestureEvent; using blink::WebInputEvent; @@ -34,6 +35,13 @@ gfx::Vector2dF FlingBooster::GetVelocityForFlingStart( fling_start.GetType()); gfx::Vector2dF velocity(fling_start.data.fling_start.velocity_x, fling_start.data.fling_start.velocity_y); + + static const bool reduce_horizontal_fling_velocity = + base::FeatureList::IsEnabled(features::kReduceHorizontalFlingVelocity); + if (reduce_horizontal_fling_velocity) { + // Reduce the horizontal velocity of flings. + velocity.Scale(0.2f, 1.0f); + } TRACE_EVENT2("input", "FlingBooster::GetVelocityForFlingStart", "vx", velocity.x(), "vy", velocity.y()); diff --git a/chromium/ui/events/cocoa/cocoa_event_utils.mm b/chromium/ui/events/cocoa/cocoa_event_utils.mm index d70b3dc6b18..9323e555a25 100644 --- a/chromium/ui/events/cocoa/cocoa_event_utils.mm +++ b/chromium/ui/events/cocoa/cocoa_event_utils.mm @@ -4,6 +4,8 @@ #import "ui/events/cocoa/cocoa_event_utils.h" +#include // for + #include "base/mac/scoped_cftyperef.h" #include "ui/events/event_constants.h" #include "ui/events/event_utils.h" @@ -101,38 +103,38 @@ bool IsKeyUpEvent(NSEvent* event) { const unsigned int kRightControlKeyMask = 1 << 13; switch ([event keyCode]) { - case 54: // Right Command - return IsModifierKeyUp([event modifierFlags], kRightCommandKeyMask, - kLeftCommandKeyMask, NSCommandKeyMask); - case 55: // Left Command + case kVK_Command: return IsModifierKeyUp([event modifierFlags], kLeftCommandKeyMask, kRightCommandKeyMask, NSCommandKeyMask); + case kVK_RightCommand: + return IsModifierKeyUp([event modifierFlags], kRightCommandKeyMask, + kLeftCommandKeyMask, NSCommandKeyMask); - case 57: // Capslock + case kVK_CapsLock: return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0; - case 56: // Left Shift + case kVK_Shift: return IsModifierKeyUp([event modifierFlags], kLeftShiftKeyMask, kRightShiftKeyMask, NSShiftKeyMask); - case 60: // Right Shift + case kVK_RightShift: return IsModifierKeyUp([event modifierFlags], kRightShiftKeyMask, kLeftShiftKeyMask, NSShiftKeyMask); - case 58: // Left Alt + case kVK_Option: return IsModifierKeyUp([event modifierFlags], kLeftAlternateKeyMask, kRightAlternateKeyMask, NSAlternateKeyMask); - case 61: // Right Alt + case kVK_RightOption: return IsModifierKeyUp([event modifierFlags], kRightAlternateKeyMask, kLeftAlternateKeyMask, NSAlternateKeyMask); - case 59: // Left Ctrl + case kVK_Control: return IsModifierKeyUp([event modifierFlags], kLeftControlKeyMask, kRightControlKeyMask, NSControlKeyMask); - case 62: // Right Ctrl + case kVK_RightControl: return IsModifierKeyUp([event modifierFlags], kRightControlKeyMask, kLeftControlKeyMask, NSControlKeyMask); - case 63: // Function + case kVK_Function: return ([event modifierFlags] & NSFunctionKeyMask) == 0; } return false; diff --git a/chromium/ui/events/devices/device_data_manager.cc b/chromium/ui/events/devices/device_data_manager.cc index cf43bedaca8..f2b02e8a9f6 100644 --- a/chromium/ui/events/devices/device_data_manager.cc +++ b/chromium/ui/events/devices/device_data_manager.cc @@ -288,6 +288,15 @@ void DeviceDataManager::RemoveObserver(InputDeviceEventObserver* observer) { observers_.RemoveObserver(observer); } +void DeviceDataManager::ResetDeviceListsForTest() { + touchscreen_devices_.clear(); + keyboard_devices_.clear(); + mouse_devices_.clear(); + touchpad_devices_.clear(); + uncategorized_devices_.clear(); + device_lists_complete_ = false; +} + void DeviceDataManager::SetTouchscreensEnabled(bool enabled) { touch_screens_enabled_ = enabled; } diff --git a/chromium/ui/events/devices/device_data_manager.h b/chromium/ui/events/devices/device_data_manager.h index 08fb678e8c9..b15a3c43841 100644 --- a/chromium/ui/events/devices/device_data_manager.h +++ b/chromium/ui/events/devices/device_data_manager.h @@ -68,6 +68,11 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager void AddObserver(InputDeviceEventObserver* observer); void RemoveObserver(InputDeviceEventObserver* observer); + // Resets all device lists and |device_lists_complete_|. This method exists + // because the DeviceDataManager instance is created early in test suite setup + // and is hard to replace for tests that require a fresh one. + void ResetDeviceListsForTest(); + protected: DeviceDataManager(); diff --git a/chromium/ui/events/devices/input_device_observer_win.cc b/chromium/ui/events/devices/input_device_observer_win.cc index 33b901c6a12..c7d485aa6ce 100644 --- a/chromium/ui/events/devices/input_device_observer_win.cc +++ b/chromium/ui/events/devices/input_device_observer_win.cc @@ -4,12 +4,12 @@ #include "ui/events/devices/input_device_observer_win.h" +#include #include #include "base/bind.h" #include "base/callback.h" #include "base/memory/singleton.h" -#include "base/strings/string16.h" #include diff --git a/chromium/ui/events/event.cc b/chromium/ui/events/event.cc index e02c15865d6..5ab31094b77 100644 --- a/chromium/ui/events/event.cc +++ b/chromium/ui/events/event.cc @@ -17,7 +17,6 @@ #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" -#include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -840,7 +839,7 @@ KeyEvent::KeyEvent(EventType type, is_char_(is_char), key_(key) {} -KeyEvent::KeyEvent(base::char16 character, +KeyEvent::KeyEvent(char16_t character, KeyboardCode key_code, DomCode code, int flags, @@ -1001,9 +1000,9 @@ bool KeyEvent::IsRepeated(KeyEvent** last_key_event) { KeyEvent** KeyEvent::GetLastKeyEvent() { #if defined(USE_X11) || defined(USE_OZONE) // Use a different static variable for key events that have non standard - // state masks as it may be reposted by an IME. IBUS-GTK uses this field - // to detect the re-posted event for example. crbug.com/385873. - return properties() && properties()->contains(kPropertyKeyboardIBusFlag) + // state masks as it may be reposted by an IME. IBUS-GTK and fcitx-GTK uses + // this field to detect the re-posted event for example. crbug.com/385873. + return properties() && properties()->contains(kPropertyKeyboardImeFlag) ? &last_ibus_key_event_ : &last_key_event_; #else @@ -1018,7 +1017,7 @@ DomKey KeyEvent::GetDomKey() const { return key_; } -base::char16 KeyEvent::GetCharacter() const { +char16_t KeyEvent::GetCharacter() const { // Determination of key_ may be done lazily. if (key_ == DomKey::NONE) ApplyLayout(); @@ -1026,7 +1025,7 @@ base::char16 KeyEvent::GetCharacter() const { // Historically ui::KeyEvent has held only BMP characters. // Until this explicitly changes, require |key_| to hold a BMP character. DomKey::Base utf32_character = key_.ToCharacter(); - base::char16 ucs2_character = static_cast(utf32_character); + char16_t ucs2_character{utf32_character}; DCHECK_EQ(static_cast(ucs2_character), utf32_character); // Check if the control character is down. Note that ALTGR is represented // on Windows as CTRL|ALT, so we need to make sure that is not set. @@ -1044,7 +1043,7 @@ base::char16 KeyEvent::GetCharacter() const { return 0; } -base::char16 KeyEvent::GetText() const { +char16_t KeyEvent::GetText() const { if ((flags() & EF_CONTROL_DOWN) != 0) { DomKey key; KeyboardCode key_code; @@ -1054,7 +1053,7 @@ base::char16 KeyEvent::GetText() const { return GetUnmodifiedText(); } -base::char16 KeyEvent::GetUnmodifiedText() const { +char16_t KeyEvent::GetUnmodifiedText() const { if (!is_char_ && (key_code_ == VKEY_RETURN)) return '\r'; return GetCharacter(); diff --git a/chromium/ui/events/event.h b/chromium/ui/events/event.h index 2c9c0bda582..8a5d246439a 100644 --- a/chromium/ui/events/event.h +++ b/chromium/ui/events/event.h @@ -14,7 +14,6 @@ #include "base/containers/flat_map.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "base/time/time.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_event_details.h" @@ -787,7 +786,7 @@ class EVENTS_EXPORT KeyEvent : public Event { bool is_char = false); // Create a character event. - KeyEvent(base::char16 character, + KeyEvent(char16_t character, KeyboardCode key_code, DomCode code, int flags, @@ -809,22 +808,22 @@ class EVENTS_EXPORT KeyEvent : public Event { // which allows an I18N virtual keyboard to fabricate a keyboard event that // does not have a corresponding KeyboardCode (example: U+00E1 Latin small // letter A with acute, U+0410 Cyrillic capital letter A). - void set_character(base::char16 character) { + void set_character(char16_t character) { key_ = DomKey::FromCharacter(character); } // Gets the character generated by this key event. It only supports Unicode // BMP characters. - base::char16 GetCharacter() const; + char16_t GetCharacter() const; // If this is a keystroke event with key_code_ VKEY_RETURN, returns '\r'; // otherwise returns the same as GetCharacter(). - base::char16 GetUnmodifiedText() const; + char16_t GetUnmodifiedText() const; // If the Control key is down in the event, returns a layout-independent // character (corresponding to US layout); otherwise returns the same // as GetUnmodifiedText(). - base::char16 GetText() const; + char16_t GetText() const; // True if this is a character event, false if this is a keystroke event. bool is_char() const { return is_char_; } diff --git a/chromium/ui/events/event_unittest.cc b/chromium/ui/events/event_unittest.cc index 79ac1dd3cbf..e651e1dbf36 100644 --- a/chromium/ui/events/event_unittest.cc +++ b/chromium/ui/events/event_unittest.cc @@ -7,10 +7,15 @@ #include #include +#include #include +#include #include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/simple_test_tick_clock.h" +#include "base/test/task_environment.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ui_base_features.h" @@ -654,6 +659,12 @@ TEST(EventTest, EventLatencyOSMouseWheelHistogram) { 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); #endif } @@ -830,6 +841,226 @@ 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}; +}; + +class EventLatencyTickCountTest + : public EventLatencyTestBase, + public ::testing::WithParamInterface { + public: + EventLatencyTickCountTest() { + SetEventLatencyTickClockForTesting(&tick_clock_); + } + + ~EventLatencyTickCountTest() { SetEventLatencyTickClockForTesting(nullptr); } + + protected: + void UpdateTickClock(DWORD timestamp) { + tick_clock_.SetNowTicks(base::TimeTicks() + + base::TimeDelta::FromMilliseconds(timestamp)); + } + + // The inherited |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 + // ::GetTickCount. + constexpr DWORD timestamp_msec = std::numeric_limits::max() - 10; + + const std::string suffix = GetParam().histogram_suffix; + + // This test will create several events with the same timestamp, and change + // the mocked result of ::GetTickCount for each measurement. This makes it + // easier to test the edge case when the 32-bit ::GetTickCount overflows. + + // Measure the latency of an event that's processed not long after the OS + // timestamp. + UpdateTickClock(timestamp_msec + 5); + { + base::HistogramTester histogram_tester; + ComputeEventLatencyOSWinFromTickCount(GetParam().event_type, timestamp_msec, + base::TimeTicks::Now()); + ExpectValidHistograms(histogram_tester, + base::TimeDelta::FromMilliseconds(5), suffix); + } + + // Simulate ::GetTickCount advancing 15 msec, which wraps around past 0. + constexpr DWORD wrapped_timestamp_msec = timestamp_msec + 15; + static_assert(wrapped_timestamp_msec == 4, + "timestamp should have wrapped around"); + UpdateTickClock(wrapped_timestamp_msec); + { + base::HistogramTester histogram_tester; + ComputeEventLatencyOSWinFromTickCount(GetParam().event_type, timestamp_msec, + base::TimeTicks::Now()); + ExpectValidHistograms(histogram_tester, + base::TimeDelta::FromMilliseconds(15), suffix); + } + + // Simulate an event with a bogus timestamp. + UpdateTickClock(timestamp_msec - 1000); + { + base::HistogramTester histogram_tester; + ComputeEventLatencyOSWinFromTickCount(GetParam().event_type, timestamp_msec, + base::TimeTicks::Now()); + ExpectInvalidHistograms(histogram_tester, suffix); + } +} + +INSTANTIATE_TEST_SUITE_P(All, + EventLatencyTickCountTest, + ::testing::ValuesIn(kEventLatencyTickCountTestCases)); + +using EventLatencyPerformanceCounterTest = EventLatencyTestBase; + +TEST_F(EventLatencyPerformanceCounterTest, + ComputeEventLatencyOSWinFromPerformanceCounter) { + // Make sure there's enough time before Now() to create an event that's + // several minutes old. + task_environment_.AdvanceClock(base::TimeDelta::FromMinutes(5)); + + // Convert the current time to units directly compatible with the Performance + // Counter. + LARGE_INTEGER ticks_per_sec = {}; + if (!::QueryPerformanceFrequency(&ticks_per_sec) || + ticks_per_sec.QuadPart <= 0 || !base::TimeTicks::IsHighResolution()) { + // Skip this test when the performance counter is unavailable or + // unreliable. (It's unlikely, but possible, that IsHighResolution is false + // even if the performance counter works - see InitializeNowFunctionPointer + // in time_win.cc - so also skip the test in this case.) + return; + } + const auto ticks_per_second = ticks_per_sec.QuadPart; + UINT64 current_timestamp = + base::TimeTicks::Now().since_origin().InSecondsF() * ticks_per_second; + + // Event created shortly before now. + { + 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"); + } + + // Event created several minutes before now (IsValidTimebase should return + // false). + { + base::HistogramTester histogram_tester; + ComputeEventLatencyOSWinFromPerformanceCounter( + ET_TOUCH_PRESSED, current_timestamp - 5 * 60 * ticks_per_second, + base::TimeTicks::Now()); + ExpectInvalidHistograms(histogram_tester, "TOUCH_PRESSED"); + } + + // Event created in the future (IsValidTimebase should return false). + { + base::HistogramTester histogram_tester; + ComputeEventLatencyOSWinFromPerformanceCounter( + ET_TOUCH_PRESSED, current_timestamp + ticks_per_second, + base::TimeTicks::Now()); + ExpectInvalidHistograms(histogram_tester, "TOUCH_PRESSED"); + } + + // Event that should not be recorded. + { + base::HistogramTester histogram_tester; + ComputeEventLatencyOSWinFromPerformanceCounter( + ET_TOUCH_MOVED, current_timestamp - 10, base::TimeTicks::Now()); + ExpectNoHistograms(histogram_tester, "TOUCH_MOVED"); + } +} + #endif // defined(OS_WIN) } // namespace ui diff --git a/chromium/ui/events/event_utils.cc b/chromium/ui/events/event_utils.cc index 487991a97f6..93045d6ba57 100644 --- a/chromium/ui/events/event_utils.cc +++ b/chromium/ui/events/event_utils.cc @@ -4,20 +4,127 @@ #include "ui/events/event_utils.h" +#include #include #include #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" namespace ui { namespace { + int g_custom_event_types = ET_LAST; + +#if defined(OS_WIN) + +#define UMA_HISTOGRAM_WIN_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 + } // namespace std::unique_ptr EventFromNative(const PlatformEvent& native_event) { @@ -83,12 +190,86 @@ 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 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(); + 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::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); +} +#endif + void ComputeEventLatencyOS(const PlatformEvent& native_event) { base::TimeTicks current_time = EventTimeForNow(); base::TimeTicks time_stamp = EventTimeFromNative(native_event); 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 + switch (type) { #if defined(OS_APPLE) // On Mac, ET_SCROLL and ET_MOUSEWHEEL represent the same class of events. diff --git a/chromium/ui/events/event_utils.h b/chromium/ui/events/event_utils.h index 63bc53eeabb..e60e7d58cba 100644 --- a/chromium/ui/events/event_utils.h +++ b/chromium/ui/events/event_utils.h @@ -8,9 +8,9 @@ #include #include +#include #include -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "build/build_config.h" #include "ui/display/display.h" @@ -33,6 +33,7 @@ class Vector2d; } // namespace gfx namespace base { +class TickClock; class TimeTicks; } @@ -49,12 +50,20 @@ constexpr char kPropertyKeyboardGroup[] = "_keyevent_kbd_group_"; // Key used to store 'hardware key code' values in Event::Properties constexpr char kPropertyKeyboardHwKeyCode[] = "_keyevent_kbd_hw_keycode_"; -// IBus specific Event::Properties constants. ibus-gtk in async mode uses -// gtk-specific XKeyEvent::state bits 24 and 25 for its key events. +// Event::Properties constants for IBus-GTK and fcitx-GTK. +// Both of them in async mode use gtk-specific XKeyEvent::state bits 24 and 25. +// 24 is handled and 25 is ignored. +// Note that they use more bits, but Chrome does not handle it now. +// cf) +// https://github.com/ibus/ibus/blob/dd4cc5b028c35f9bb8fa9d3bdc8f26bcdfc43d40/src/ibustypes.h#L88 +// https://github.com/fcitx/fcitx/blob/289b2f674d95651d4e0d0c77a48e3a2f0da40efe/src/lib/fcitx-utils/keysym.h#L47 // https://mail.gnome.org/archives/gtk-devel-list/2013-June/msg00003.html -constexpr char kPropertyKeyboardIBusFlag[] = "_keyevent_kbd_ibus_ime_flags_"; -constexpr unsigned int kPropertyKeyboardIBusFlagOffset = 24; -constexpr unsigned int kPropertyKeyboardIBusFlagMask = 0x03; +constexpr char kPropertyKeyboardImeFlag[] = "_keyevent_kbd_ime_flags_"; +constexpr unsigned int kPropertyKeyboardImeFlagOffset = 24; +constexpr unsigned int kPropertyKeyboardImeFlagMask = 0x03; +// Ignored is the 25-th bit. +constexpr unsigned int kPropertyKeyboardImeIgnoredFlag = + 1 << (25 - kPropertyKeyboardImeFlagOffset); // Key used to store mouse event flag telling ET_MOUSE_EXITED must actually be // interpreted as "crossing intermediate window" in blink context. @@ -161,6 +170,26 @@ EVENTS_EXPORT display::Display::TouchSupport GetInternalDisplayTouchSupport(); EVENTS_EXPORT void ComputeEventLatencyOS(const PlatformEvent& native_event); #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( + ui::EventType event_type, + DWORD event_time, + 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( + ui::EventType event_type, + UINT64 event_time, + base::TimeTicks current_time); + EVENTS_EXPORT int GetModifiersFromKeyState(); // Returns true if |message| identifies a mouse event that was generated as the diff --git a/chromium/ui/events/fuchsia/OWNERS b/chromium/ui/events/fuchsia/OWNERS index e69de29bb2d..e7034eabb1e 100644 --- a/chromium/ui/events/fuchsia/OWNERS +++ b/chromium/ui/events/fuchsia/OWNERS @@ -0,0 +1 @@ +file://build/fuchsia/OWNERS diff --git a/chromium/ui/events/fuchsia/input_event_dispatcher.cc b/chromium/ui/events/fuchsia/input_event_dispatcher.cc index f557679808b..f2404852c74 100644 --- a/chromium/ui/events/fuchsia/input_event_dispatcher.cc +++ b/chromium/ui/events/fuchsia/input_event_dispatcher.cc @@ -10,31 +10,15 @@ #include "base/memory/ptr_util.h" #include "base/notreached.h" #include "ui/events/event.h" -#include "ui/events/fuchsia/input_event_dispatcher_delegate.h" +#include "ui/events/fuchsia/input_event_sink.h" #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/keycodes/keyboard_code_conversion.h" namespace ui { -namespace { -int KeyModifiersToFlags(int modifiers) { - int flags = 0; - if (modifiers & fuchsia::ui::input::kModifierShift) - flags |= EF_SHIFT_DOWN; - if (modifiers & fuchsia::ui::input::kModifierControl) - flags |= EF_CONTROL_DOWN; - if (modifiers & fuchsia::ui::input::kModifierAlt) - flags |= EF_ALT_DOWN; - // TODO(crbug.com/850697): Add AltGraph support. - return flags; -} - -} // namespace - -InputEventDispatcher::InputEventDispatcher( - InputEventDispatcherDelegate* delegate) - : delegate_(delegate) { - DCHECK(delegate_); +InputEventDispatcher::InputEventDispatcher(InputEventSink* event_sink) + : event_sink_(event_sink) { + DCHECK(event_sink_); } InputEventDispatcher::~InputEventDispatcher() = default; @@ -55,8 +39,7 @@ bool InputEventDispatcher::ProcessEvent( } case fuchsia::ui::input::InputEvent::Tag::kKeyboard: - return ProcessKeyboardEvent(event.keyboard()); - + // Only input3 should be used for receiving keyboard events. case fuchsia::ui::input::InputEvent::Tag::kFocus: case fuchsia::ui::input::InputEvent::Tag::Invalid: return false; @@ -103,7 +86,7 @@ bool InputEventDispatcher::ProcessMouseEvent( base::TimeTicks::FromZxTime(event.event_time), buttons_flags, buttons_flags); mouse_event.set_location_f(gfx::PointF(event.x, event.y)); - delegate_->DispatchEvent(&mouse_event); + event_sink_->DispatchEvent(&mouse_event); return mouse_event.handled(); } @@ -143,48 +126,8 @@ bool InputEventDispatcher::ProcessTouchEvent( pointer_details); touch_event.set_hovering(hovering); touch_event.set_location_f(gfx::PointF(event.x, event.y)); - delegate_->DispatchEvent(&touch_event); + event_sink_->DispatchEvent(&touch_event); return touch_event.handled(); } -bool InputEventDispatcher::ProcessKeyboardEvent( - const fuchsia::ui::input::KeyboardEvent& event) const { - EventType event_type; - - switch (event.phase) { - case fuchsia::ui::input::KeyboardEventPhase::PRESSED: - case fuchsia::ui::input::KeyboardEventPhase::REPEAT: - event_type = ET_KEY_PRESSED; - break; - - case fuchsia::ui::input::KeyboardEventPhase::RELEASED: - event_type = ET_KEY_RELEASED; - break; - - case fuchsia::ui::input::KeyboardEventPhase::CANCELLED: - NOTIMPLEMENTED() << "Key event cancellation is not supported."; - event_type = ET_KEY_RELEASED; - break; - } - - DomCode dom_code = KeycodeConverter::NativeKeycodeToDomCode(event.hid_usage); - DomKey dom_key; - KeyboardCode key_code; - if (!DomCodeToUsLayoutDomKey(dom_code, KeyModifiersToFlags(event.modifiers), - &dom_key, &key_code)) { - LOG(ERROR) << "DomCodeToUsLayoutDomKey() failed for usb_key: " - << event.hid_usage; - key_code = VKEY_UNKNOWN; - } - - if (event.code_point) - dom_key = DomKey::FromCharacter(event.code_point); - - ui::KeyEvent key_event(event_type, key_code, dom_code, - KeyModifiersToFlags(event.modifiers), dom_key, - base::TimeTicks::FromZxTime(event.event_time)); - delegate_->DispatchEvent(&key_event); - return key_event.handled(); -} - } // namespace ui diff --git a/chromium/ui/events/fuchsia/input_event_dispatcher.h b/chromium/ui/events/fuchsia/input_event_dispatcher.h index 6307773edd8..731b7514a77 100644 --- a/chromium/ui/events/fuchsia/input_event_dispatcher.h +++ b/chromium/ui/events/fuchsia/input_event_dispatcher.h @@ -12,14 +12,14 @@ namespace ui { -class InputEventDispatcherDelegate; +class InputEventSink; // Translates Fuchsia input events to Chrome ui::Events. class EVENTS_EXPORT InputEventDispatcher { public: - // |delegate|: The recipient of any Chrome events that are processed from + // |event_sink|: The recipient of any Chrome events that are processed from // Fuchsia events. - explicit InputEventDispatcher(InputEventDispatcherDelegate* delegate); + explicit InputEventDispatcher(InputEventSink* event_sink); ~InputEventDispatcher(); // Processes a Fuchsia |event| and dispatches Chrome ui::Events from it. @@ -31,10 +31,8 @@ class EVENTS_EXPORT InputEventDispatcher { private: bool ProcessMouseEvent(const fuchsia::ui::input::PointerEvent& event) const; bool ProcessTouchEvent(const fuchsia::ui::input::PointerEvent& event) const; - bool ProcessKeyboardEvent( - const fuchsia::ui::input::KeyboardEvent& event) const; - InputEventDispatcherDelegate* delegate_; + InputEventSink* event_sink_; DISALLOW_COPY_AND_ASSIGN(InputEventDispatcher); }; diff --git a/chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h b/chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h deleted file mode 100644 index 78a70a8b327..00000000000 --- a/chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h +++ /dev/null @@ -1,22 +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. - -#ifndef UI_EVENTS_FUCHSIA_INPUT_EVENT_DISPATCHER_DELEGATE_H_ -#define UI_EVENTS_FUCHSIA_INPUT_EVENT_DISPATCHER_DELEGATE_H_ - -#include "ui/events/events_export.h" - -namespace ui { - -class Event; - -// Translates Fuchsia input events to Chrome ui::Events. -class EVENTS_EXPORT InputEventDispatcherDelegate { - public: - virtual void DispatchEvent(ui::Event* event) = 0; -}; - -} // namespace ui - -#endif // UI_EVENTS_FUCHSIA_INPUT_EVENT_DISPATCHER_DELEGATE_H_ diff --git a/chromium/ui/events/fuchsia/input_event_dispatcher_unittest.cc b/chromium/ui/events/fuchsia/input_event_dispatcher_unittest.cc index 54a14b9909b..602058f8416 100644 --- a/chromium/ui/events/fuchsia/input_event_dispatcher_unittest.cc +++ b/chromium/ui/events/fuchsia/input_event_dispatcher_unittest.cc @@ -10,7 +10,7 @@ #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event.h" -#include "ui/events/fuchsia/input_event_dispatcher_delegate.h" +#include "ui/events/fuchsia/input_event_sink.h" #include "ui/events/keycodes/dom/dom_key.h" using fuchsia::ui::input::InputEvent; @@ -20,8 +20,7 @@ using FuchsiaPointerEvent = fuchsia::ui::input::PointerEvent; namespace ui { namespace { -class InputEventDispatcherTest : public testing::Test, - public InputEventDispatcherDelegate { +class InputEventDispatcherTest : public testing::Test, public InputEventSink { public: InputEventDispatcherTest() : dispatcher_(this) {} ~InputEventDispatcherTest() override = default; @@ -181,83 +180,5 @@ TEST_F(InputEventDispatcherTest, TouchPhases) { EXPECT_EQ(nullptr, captured_event_.get()); } -TEST_F(InputEventDispatcherTest, KeyPhases) { - FuchsiaKeyboardEvent key_event; - key_event.hid_usage = 4; // Corresponds to pressing "a" on a US keyboard. - key_event.phase = fuchsia::ui::input::KeyboardEventPhase::PRESSED; - - InputEvent event; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_PRESSED, captured_event_->type()); - ResetCapturedEvent(); - - key_event.phase = fuchsia::ui::input::KeyboardEventPhase::REPEAT; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_PRESSED, captured_event_->type()); - ResetCapturedEvent(); - - key_event.phase = fuchsia::ui::input::KeyboardEventPhase::RELEASED; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_RELEASED, captured_event_->type()); - ResetCapturedEvent(); - - key_event.phase = fuchsia::ui::input::KeyboardEventPhase::CANCELLED; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_RELEASED, captured_event_->type()); -} - -TEST_F(InputEventDispatcherTest, KeyModifiers) { - FuchsiaKeyboardEvent key_event; - key_event.hid_usage = 4; // Corresponds to pressing "a" on a US keyboard. - key_event.phase = fuchsia::ui::input::KeyboardEventPhase::PRESSED; - - InputEvent event; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_PRESSED, captured_event_->type()); - EXPECT_EQ('a', - DomKey(captured_event_->AsKeyEvent()->GetDomKey()).ToCharacter()); - EXPECT_EQ('a', captured_event_->AsKeyEvent()->GetCharacter()); - ResetCapturedEvent(); - - key_event.modifiers = fuchsia::ui::input::kModifierShift; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_PRESSED, captured_event_->type()); - EXPECT_EQ('A', - DomKey(captured_event_->AsKeyEvent()->GetDomKey()).ToCharacter()); - EXPECT_EQ('A', captured_event_->AsKeyEvent()->GetCharacter()); - EXPECT_TRUE(captured_event_->IsShiftDown()); - EXPECT_FALSE(captured_event_->IsControlDown()); - EXPECT_FALSE(captured_event_->IsAltDown()); - ResetCapturedEvent(); - - key_event.modifiers = - fuchsia::ui::input::kModifierShift | fuchsia::ui::input::kModifierControl; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_PRESSED, captured_event_->type()); - EXPECT_TRUE(captured_event_->IsShiftDown()); - EXPECT_TRUE(captured_event_->IsControlDown()); - EXPECT_FALSE(captured_event_->IsAltDown()); - ResetCapturedEvent(); - - key_event.modifiers = fuchsia::ui::input::kModifierShift | - fuchsia::ui::input::kModifierControl | - fuchsia::ui::input::kModifierAlt; - event.set_keyboard(key_event); - dispatcher_.ProcessEvent(event); - EXPECT_EQ(ET_KEY_PRESSED, captured_event_->type()); - EXPECT_EQ('A', - DomKey(captured_event_->AsKeyEvent()->GetDomKey()).ToCharacter()); - EXPECT_TRUE(captured_event_->IsShiftDown()); - EXPECT_TRUE(captured_event_->IsControlDown()); - EXPECT_TRUE(captured_event_->IsAltDown()); -} - } // namespace } // namespace ui diff --git a/chromium/ui/events/fuchsia/input_event_sink.h b/chromium/ui/events/fuchsia/input_event_sink.h new file mode 100644 index 00000000000..0d138ff2074 --- /dev/null +++ b/chromium/ui/events/fuchsia/input_event_sink.h @@ -0,0 +1,22 @@ +// 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. + +#ifndef UI_EVENTS_FUCHSIA_INPUT_EVENT_SINK_H_ +#define UI_EVENTS_FUCHSIA_INPUT_EVENT_SINK_H_ + +#include "ui/events/events_export.h" + +namespace ui { + +class Event; + +// Translates Fuchsia input events to Chrome ui::Events. +class EVENTS_EXPORT InputEventSink { + public: + virtual void DispatchEvent(ui::Event* event) = 0; +}; + +} // namespace ui + +#endif // UI_EVENTS_FUCHSIA_INPUT_EVENT_SINK_H_ diff --git a/chromium/ui/events/gesture_detection/gesture_provider.cc b/chromium/ui/events/gesture_detection/gesture_provider.cc index 87c7324d18b..d451fcdcc0e 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider.cc +++ b/chromium/ui/events/gesture_detection/gesture_provider.cc @@ -814,13 +814,18 @@ bool GestureProvider::OnTouchEvent(const MotionEvent& event) { GetMotionEventActionName(event.GetAction())); DCHECK_NE(0u, event.GetPointerCount()); + // We record the histograms before the |CanHandle()| call below because we + // want to check the event stream before gesture processing takes place. For + // example, we want to see |MotionEvent::Action::UP| event even for a panning + // gesture where the UP is not dispatched to content. + uma_histogram_.RecordTouchEvent(event); + if (!CanHandle(event)) return false; OnTouchEventHandlingBegin(event); gesture_listener_->OnTouchEvent(event); OnTouchEventHandlingEnd(event); - uma_histogram_.RecordTouchEvent(event); return true; } diff --git a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc index 6beca1fbe08..061a3a6b663 100644 --- a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc +++ b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc @@ -3063,4 +3063,166 @@ TEST_F(GestureProviderTest, SingleTapRepeatLengthOfOne) { EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap_count()); } +// Test for Event.MaxDragDistance.* histograms with taps. +TEST_F(GestureProviderTest, MaxDragDistanceHistogramsWithTap) { + base::HistogramTester histograms_tester; + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 0); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 0); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 0); + + // A tap of type FINGER adds appropriate counts. + base::TimeTicks event_time = base::TimeTicks::Now(); + MockMotionEvent event = + ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectBucketCount("Event.MaxDragDistance.FINGER", 0, 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 0); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 0); + + // A tap of type STYLUS adds appropriate counts. + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, MotionEvent::ToolType::STYLUS); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP); + event.SetToolType(0, MotionEvent::ToolType::STYLUS); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectBucketCount("Event.MaxDragDistance.STYLUS", 0, 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 0); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 1); + + // A tap of type ERASER adds appropriate counts. + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, MotionEvent::ToolType::ERASER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP); + event.SetToolType(0, MotionEvent::ToolType::ERASER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectBucketCount("Event.MaxDragDistance.ERASER", 0, 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 1); + + // A canceled tap is not counted. + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::CANCEL); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 1); + + // A multifinger tap is not counted. + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_DOWN); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_UP); + event.SetToolType(0, MotionEvent::ToolType::STYLUS); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP); + event.SetToolType(0, MotionEvent::ToolType::STYLUS); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 1); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 1); +} + +// Test for Event.MaxDragDistance.* histograms with drags. +TEST_F(GestureProviderTest, MaxDragDistanceHistogramsWithDrag) { + base::HistogramTester histograms_tester; + + // A tiny 1px drag is counted in appropriate distance bucket. + base::TimeTicks event_time = base::TimeTicks::Now(); + MockMotionEvent event = + ObtainMotionEvent(event_time, MotionEvent::Action::DOWN, 10, 10); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 10, 11); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP, 10, 11); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectBucketCount("Event.MaxDragDistance.FINGER", 1, 1); + + // A small 10px drag is counted in appropriate distance bucket. + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN, 10, 10); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 10, 20); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP, 10, 20); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectBucketCount("Event.MaxDragDistance.FINGER", 10, 1); + + // A long 100px drag is counted in appropriate distance bucket. + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN, 10, 10); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 10, 110); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event_time += kOneMicrosecond; + event = ObtainMotionEvent(event_time, MotionEvent::Action::UP, 10, 110); + event.SetToolType(0, MotionEvent::ToolType::FINGER); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + histograms_tester.ExpectBucketCount("Event.MaxDragDistance.FINGER", 100, 1); + + // We have 3 counts in total + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.ERASER", 0); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.FINGER", 3); + histograms_tester.ExpectTotalCount("Event.MaxDragDistance.STYLUS", 0); +} + } // namespace ui diff --git a/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.cc b/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.cc index 95295a0ebe1..a286b10f02f 100644 --- a/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.cc +++ b/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.cc @@ -9,44 +9,55 @@ namespace ui { -GestureTouchUMAHistogram::GestureTouchUMAHistogram() - : max_distance_from_start_squared_(0), is_single_finger_(true) { -} - -GestureTouchUMAHistogram::~GestureTouchUMAHistogram() { -} - void GestureTouchUMAHistogram::RecordGestureEvent( const GestureEventData& gesture) { UMA_HISTOGRAM_ENUMERATION( "Event.GestureCreated", UMAEventTypeFromEvent(gesture), UMA_ET_COUNT); } +#define RECORD_MAX_DRAG_DISTANCE(HISTOGRAM_NAME, DIST_SQUARED) \ + UMA_HISTOGRAM_CUSTOM_COUNTS( \ + HISTOGRAM_NAME, static_cast(sqrt(DIST_SQUARED)), 1, 1500, 50) + void GestureTouchUMAHistogram::RecordTouchEvent(const MotionEvent& event) { - if (event.GetAction() == MotionEvent::Action::DOWN) { - start_time_ = event.GetEventTime(); - start_touch_position_ = gfx::Point(event.GetX(), event.GetY()); - is_single_finger_ = true; - max_distance_from_start_squared_ = 0; - } else if (event.GetAction() == MotionEvent::Action::MOVE && - is_single_finger_) { - float cur_dist = (start_touch_position_ - - gfx::Point(event.GetX(), event.GetY())).LengthSquared(); - if (cur_dist > max_distance_from_start_squared_) - max_distance_from_start_squared_ = cur_dist; - } else { - if (event.GetAction() == MotionEvent::Action::UP && is_single_finger_) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Event.TouchMaxDistance", - static_cast(sqrt(max_distance_from_start_squared_)), - 1, - 1500, - 50); + switch (event.GetAction()) { + case MotionEvent::Action::DOWN: + tool_type_ = event.GetToolType(); + start_touch_position_ = gfx::Point(event.GetX(), event.GetY()); + is_single_finger_ = true; + max_distance_from_start_squared_ = 0; + break; - base::TimeDelta duration = event.GetEventTime() - start_time_; - UMA_HISTOGRAM_TIMES("Event.TouchDuration", duration); - } - is_single_finger_ = false; + case MotionEvent::Action::MOVE: + if (is_single_finger_) { + float cur_dist = + (start_touch_position_ - gfx::Point(event.GetX(), event.GetY())) + .LengthSquared(); + if (cur_dist > max_distance_from_start_squared_) + max_distance_from_start_squared_ = cur_dist; + } + break; + + case MotionEvent::Action::UP: + if (is_single_finger_) { + if (tool_type_ == MotionEvent::ToolType::FINGER) { + RECORD_MAX_DRAG_DISTANCE("Event.MaxDragDistance.FINGER", + max_distance_from_start_squared_); + } else if (tool_type_ == MotionEvent::ToolType::STYLUS) { + RECORD_MAX_DRAG_DISTANCE("Event.MaxDragDistance.STYLUS", + max_distance_from_start_squared_); + } else if (tool_type_ == MotionEvent::ToolType::ERASER) { + RECORD_MAX_DRAG_DISTANCE("Event.MaxDragDistance.ERASER", + max_distance_from_start_squared_); + } + is_single_finger_ = false; + } + break; + + default: + // We expect either a POINTER_DOWN (when a secondary pointer became + // active) or a CANCEL (when an active pointer becomes invalid). + is_single_finger_ = false; } } 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 a10e6d57fcb..c14ef2c2e96 100644 --- a/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h +++ b/chromium/ui/events/gesture_detection/gesture_touch_uma_histogram.h @@ -62,23 +62,20 @@ enum UMAEventType { // targetted to which components etc.) class GESTURE_DETECTION_EXPORT GestureTouchUMAHistogram { public: - GestureTouchUMAHistogram(); - ~GestureTouchUMAHistogram(); - static void RecordGestureEvent(const ui::GestureEventData& gesture); void RecordTouchEvent(const ui::MotionEvent& event); private: static UMAEventType UMAEventTypeFromEvent(const GestureEventData& gesture); - // The first finger's press time. - base::TimeTicks start_time_; - // The first finger's press location. + // The first touch point's tool type. + ui::MotionEvent::ToolType tool_type_ = ui::MotionEvent::ToolType::UNKNOWN; + // The first touch point's initial location. gfx::Point start_touch_position_; // The maximum distance the first touch point travelled from its starting // location in pixels. - float max_distance_from_start_squared_; - bool is_single_finger_; + float max_distance_from_start_squared_ = 0.f; + bool is_single_finger_ = false; }; } // namespace ui diff --git a/chromium/ui/events/keycodes/dom_us_layout_data.h b/chromium/ui/events/keycodes/dom_us_layout_data.h index fca30ec7702..a6ad3809d68 100644 --- a/chromium/ui/events/keycodes/dom_us_layout_data.h +++ b/chromium/ui/events/keycodes/dom_us_layout_data.h @@ -14,7 +14,7 @@ namespace ui { // interpretation when there is no other way to map a physical key. const struct PrintableCodeEntry { DomCode dom_code; - base::char16 character[2]; // normal, shift + char16_t character[2]; // normal, shift } kPrintableCodeMap[] = { {DomCode::US_A, {'a', 'A'}}, {DomCode::US_B, {'b', 'B'}}, diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion.cc b/chromium/ui/events/keycodes/keyboard_code_conversion.cc index 4450e7ff7d2..143e054fa2e 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion.cc @@ -24,7 +24,7 @@ bool IsRightSideDomCode(DomCode code) { } // anonymous namespace -base::char16 DomCodeToUsLayoutCharacter(DomCode dom_code, int flags) { +char16_t DomCodeToUsLayoutCharacter(DomCode dom_code, int flags) { DomKey dom_key; KeyboardCode key_code; if (DomCodeToUsLayoutDomKey(dom_code, flags, &dom_key, &key_code) && @@ -54,7 +54,7 @@ bool DomCodeToUsLayoutDomKey(DomCode dom_code, for (const auto& it : kPrintableCodeMap) { if (it.dom_code == dom_code) { int state = ((flags & EF_SHIFT_DOWN) == EF_SHIFT_DOWN); - base::char16 ch = it.character[state]; + char16_t ch = it.character[state]; if ((flags & EF_CAPS_LOCK_ON) == EF_CAPS_LOCK_ON) { ch |= 0x20; if ((ch >= 'a') && (ch <= 'z')) diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion.h b/chromium/ui/events/keycodes/keyboard_code_conversion.h index 3450f520572..73cdecd70af 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion.h +++ b/chromium/ui/events/keycodes/keyboard_code_conversion.h @@ -5,8 +5,9 @@ #ifndef UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ #define UI_EVENTS_KEYCODES_KEYBOARD_CODE_CONVERSION_H_ +#include + #include "base/compiler_specific.h" -#include "base/strings/string16.h" #include "ui/events/events_base_export.h" #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -40,8 +41,8 @@ enum class DomCode; // Returns true and sets the output parameters if the (dom_code, flags) pair // has an interpretation in the US English layout; otherwise the output // parameters are untouched. -EVENTS_BASE_EXPORT base::char16 DomCodeToUsLayoutCharacter(DomCode dom_code, - int flags); +EVENTS_BASE_EXPORT char16_t DomCodeToUsLayoutCharacter(DomCode dom_code, + int flags); EVENTS_BASE_EXPORT bool DomCodeToUsLayoutDomKey(DomCode dom_code, int flags, DomKey* dom_key, diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm index e6384ac4314..326313e5b68 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm @@ -878,6 +878,8 @@ UniChar TranslatedUnicodeCharFromKeyCode(TISInputSourceRef input_source, CFDataRef layout_data = static_cast(TISGetInputSourceProperty( input_source, kTISPropertyUnicodeKeyLayoutData)); + if (!layout_data) + return 0xFFFD; // REPLACEMENT CHARACTER const UCKeyboardLayout* keyboard_layout = reinterpret_cast(CFDataGetBytePtr(layout_data)); diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc index d94e5a07ab8..b38af7a8010 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc @@ -1017,7 +1017,7 @@ DomKey GetDomKeyFromXEvent(const x11::Event& xev) { // https://crbug.com/633838 modifiers &= ~static_cast(x11::KeyButMask::Control); uint32_t keysym = TranslateKey(xkeycode, modifiers); - base::char16 ch = GetUnicodeCharacterFromXKeySym(keysym); + char16_t ch = GetUnicodeCharacterFromXKeySym(keysym); return XKeySymToDomKey(keysym, ch); } diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_x.h b/chromium/ui/events/keycodes/keyboard_code_conversion_x.h index 2e5c6dce472..ae3742cbf51 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion_x.h +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.h @@ -7,7 +7,8 @@ #include -#include "base/strings/string16.h" +#include + #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/keyboard_codes_posix.h" #include "ui/events/keycodes/keycodes_x_export.h" diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc index ee40330275f..2844b57ba6f 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc @@ -481,7 +481,7 @@ DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym) { return DomKey::NONE; } } -DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character) { +DomKey XKeySymToDomKey(xkb_keysym_t keysym, char16_t character) { DomKey dom_key = NonPrintableXKeySymToDomKey(keysym); if (dom_key != DomKey::NONE) return dom_key; diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h index a1f9b78704f..8f56878d4bb 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.h @@ -7,7 +7,8 @@ // These functions are used by X11 targets and by Ozone/XKBcommon targets. -#include "base/strings/string16.h" +#include + #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/xkb_keysym.h" @@ -21,10 +22,10 @@ DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym); // TODO(kpschoedel) crbug.com/442757 // Returns the dead key combining character associated with an xkb_keysym_t, // or 0 if the keysym is not recognized. -// base::char16 DeadXKeySymToCombiningCharacter(xkb_keysym_t keysym); +// char16_t DeadXKeySymToCombiningCharacter(xkb_keysym_t keysym); // Return the DomKey determined by the XKB layout result (keysym, character). -DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character); +DomKey XKeySymToDomKey(xkb_keysym_t keysym, char16_t character); } // namespace ui diff --git a/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc b/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc index e251a73f880..4838320e67d 100644 --- a/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc +++ b/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc @@ -4,8 +4,9 @@ #include "ui/events/keycodes/platform_key_map_win.h" +#include + #include "base/macros.h" -#include "base/strings/string16.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/dom/dom_code.h" diff --git a/chromium/ui/events/ozone/evdev/capture_device_capabilities.py b/chromium/ui/events/ozone/evdev/capture_device_capabilities.py index fea45085bf1..f742575f2c2 100755 --- a/chromium/ui/events/ozone/evdev/capture_device_capabilities.py +++ b/chromium/ui/events/ozone/evdev/capture_device_capabilities.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # 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. diff --git a/chromium/ui/events/ozone/evdev/capture_test_events.py b/chromium/ui/events/ozone/evdev/capture_test_events.py index 4fc4815dc13..33907c43451 100755 --- a/chromium/ui/events/ozone/evdev/capture_test_events.py +++ b/chromium/ui/events/ozone/evdev/capture_test_events.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # Copyright 2017 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. diff --git a/chromium/ui/events/ozone/evdev/event_device_info.cc b/chromium/ui/events/ozone/evdev/event_device_info.cc index 797489b3f7f..5f3ed1eb57a 100644 --- a/chromium/ui/events/ozone/evdev/event_device_info.cc +++ b/chromium/ui/events/ozone/evdev/event_device_info.cc @@ -39,6 +39,7 @@ constexpr struct { {0x045e, 0x082f}, // Microsoft Bluetooth Mouse {0x045e, 0x0b05}, // Xbox One Elite Series 2 gamepad {0x046d, 0x4069}, // Logitech MX Master 2S (Unifying) + {0x046d, 0xb011}, // Logitech M558 {0x046d, 0xb016}, // Logitech M535 {0x046d, 0xb019}, // Logitech MX Master 2S (Bluetooth) {0x046d, 0xc093}, // Logitech M500s @@ -63,6 +64,11 @@ constexpr struct { {0x413c, 0x81d5}, // Dell Active Pen PN579X }; +// Note: this is not SteelSeries's actual VID; the Stratus Duo just reports it +// incorrectly over Bluetooth. +const uint16_t kSteelSeriesStratusDuoBluetoothVendorId = 0x0111; +const uint16_t kSteelSeriesStratusDuoBluetoothProductId = 0x1431; + bool GetEventBits(int fd, const base::FilePath& path, unsigned int type, @@ -525,6 +531,13 @@ bool EventDeviceInfo::HasKeyboard() const { } bool EventDeviceInfo::HasMouse() const { + // The SteelSeries Stratus Duo claims to be a mouse over Bluetooth, preventing + // it from being set up as a gamepad correctly, so check for its vendor and + // product ID. (b/189491809) + if (input_id_.vendor == kSteelSeriesStratusDuoBluetoothVendorId && + input_id_.product == kSteelSeriesStratusDuoBluetoothProductId) { + return false; + } return HasRelXY() && !HasProp(INPUT_PROP_POINTING_STICK); } @@ -576,6 +589,8 @@ ui::InputDeviceType EventDeviceInfo::GetInputDeviceTypeFromId(input_id id) { {0x18d1, 0x503c}, // Google, Masterball PID (krane) {0x18d1, 0x503d}, // Google, Magnemite PID (kodama) {0x18d1, 0x5044}, // Google, Moonball PID (kakadu) + {0x18d1, 0x504c}, // Google, Zed PID (coachz) + {0x18d1, 0x5050}, // Google, Don PID (katsu) {0x1fd2, 0x8103}, // LG, Internal TouchScreen PID }; diff --git a/chromium/ui/events/ozone/evdev/explain_proc_bus_input_devices.py b/chromium/ui/events/ozone/evdev/explain_proc_bus_input_devices.py index e4c860e4253..714b01dabcf 100755 --- a/chromium/ui/events/ozone/evdev/explain_proc_bus_input_devices.py +++ b/chromium/ui/events/ozone/evdev/explain_proc_bus_input_devices.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # 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. diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc index 441361643d2..71f2004bf45 100644 --- a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc +++ b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc @@ -7,6 +7,8 @@ #include #include +#include + #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" @@ -243,8 +245,7 @@ void DumpTouchEventLog( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::BindOnce(&CompressDumpedLog, - base::Passed(&log_paths_to_be_compressed)), + base::BindOnce(&CompressDumpedLog, std::move(log_paths_to_be_compressed)), base::BindOnce(std::move(reply), log_paths)); } diff --git a/chromium/ui/events/ozone/layout/keyboard_layout_engine.h b/chromium/ui/events/ozone/layout/keyboard_layout_engine.h index a94a9809f37..89d9e1fbfe0 100644 --- a/chromium/ui/events/ozone/layout/keyboard_layout_engine.h +++ b/chromium/ui/events/ozone/layout/keyboard_layout_engine.h @@ -8,7 +8,6 @@ #include #include "base/component_export.h" -#include "base/strings/string16.h" #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/keyboard_codes.h" diff --git a/chromium/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc b/chromium/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc index 583515edfb2..cc0c54f8f25 100644 --- a/chromium/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc +++ b/chromium/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc @@ -185,7 +185,7 @@ void TestLookup(const char* name, KeyboardLayoutEngine* engine) { int input_flags; DomKey::Base output_dom_key; KeyboardCode output_keycode; - base::char16 output_character; + char16_t output_character; } kTestCases[] = { {DomCode::US_A, EF_NONE, DomKey::Constant<'a'>::Character, VKEY_A, 'a'}, {DomCode::US_A, EF_SHIFT_DOWN, DomKey::Constant<'A'>::Character, VKEY_A, 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 7ca33e21143..069f83c2626 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 @@ -4,7 +4,8 @@ #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h" -#include "base/strings/string16.h" +#include + #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/keyboard_code_conversion.h" 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 7f256e057af..9b26c380d6e 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 @@ -38,7 +38,7 @@ typedef base::OnceCallback= '0') && (character <= '9')) { int zero = ((xkb_keysym >= XKB_KEY_KP_0) && (xkb_keysym <= XKB_KEY_KP_9)) @@ -70,14 +70,14 @@ struct PrintableSubEntry { DomCode dom_code; bool test_shift : 1; bool test_altgr : 1; - base::char16 shift_character; - base::char16 altgr_character; + char16_t shift_character; + char16_t altgr_character; KeyboardCode key_code; }; // The two designated Unicode "not-a-character" values are used as sentinels. -const base::char16 kNone = 0xFFFE; -const base::char16 kAny = 0xFFFF; +const char16_t kNone = 0xFFFE; +const char16_t kAny = 0xFFFF; // U+0021 exclamation mark const PrintableSubEntry kU0021[] = { @@ -483,7 +483,7 @@ const PrintableSubEntry kU017E[] = { // Table mapping unshifted characters to PrintableSubEntry tables. struct PrintableMultiEntry { - base::char16 plain_character; + char16_t plain_character; const PrintableSubEntry* subtable; size_t subtable_size; }; @@ -552,7 +552,7 @@ const PrintableMultiEntry kMultiMap[] = { // Table mapping unshifted characters to VKEY values. struct PrintableSimpleEntry { - base::char16 plain_character; + char16_t plain_character; KeyboardCode key_code; }; @@ -952,7 +952,7 @@ KeyboardCode XkbKeyboardLayoutEngine::DifficultKeyboardCode( xkb_keycode_t xkb_keycode, xkb_mod_mask_t xkb_flags, xkb_keysym_t xkb_keysym, - base::char16 character) const { + char16_t character) const { // Get the layout interpretation without modifiers, so that // e.g. Ctrl+D correctly generates VKEY_D. xkb_keysym_t plain_keysym; @@ -974,13 +974,13 @@ KeyboardCode XkbKeyboardLayoutEngine::DifficultKeyboardCode( const PrintableMultiEntry* multi_end = kMultiMap + base::size(kMultiMap); const PrintableMultiEntry* multi = std::lower_bound(kMultiMap, multi_end, plain_character, - [](const PrintableMultiEntry& e, base::char16 c) { - return e.plain_character < c; - }); + [](const PrintableMultiEntry& e, char16_t c) { + return e.plain_character < c; + }); if ((multi != multi_end) && (multi->plain_character == plain_character)) { - const base::char16 kNonCharacter = kAny; - base::char16 shift_character = kNonCharacter; - base::char16 altgr_character = kNonCharacter; + const char16_t kNonCharacter = kAny; + char16_t shift_character = kNonCharacter; + char16_t altgr_character = kNonCharacter; for (size_t i = 0; i < multi->subtable_size; ++i) { if (multi->subtable[i].dom_code != dom_code) continue; @@ -1008,20 +1008,19 @@ KeyboardCode XkbKeyboardLayoutEngine::DifficultKeyboardCode( const PrintableSimpleEntry* simple_end = kSimpleMap + base::size(kSimpleMap); const PrintableSimpleEntry* simple = std::lower_bound(kSimpleMap, simple_end, plain_character, - [](const PrintableSimpleEntry& e, base::char16 c) { - return e.plain_character < c; - }); + [](const PrintableSimpleEntry& e, char16_t c) { + return e.plain_character < c; + }); if ((simple != simple_end) && (simple->plain_character == plain_character)) return simple->key_code; return VKEY_UNKNOWN; } -base::char16 XkbKeyboardLayoutEngine::XkbSubCharacter( - xkb_keycode_t xkb_keycode, - xkb_mod_mask_t base_flags, - base::char16 base_character, - xkb_mod_mask_t flags) const { +char16_t XkbKeyboardLayoutEngine::XkbSubCharacter(xkb_keycode_t xkb_keycode, + xkb_mod_mask_t base_flags, + char16_t base_character, + xkb_mod_mask_t flags) const { if (flags == base_flags) return base_character; xkb_keysym_t keysym; 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 f6a6e7b95fd..fd9948d2937 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 @@ -17,7 +17,6 @@ #include "base/memory/free_deleter.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" #include "base/task_runner.h" #include "build/chromeos_buildflags.h" #include "ui/events/keycodes/scoped_xkb.h" @@ -92,7 +91,7 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) XkbKeyboardLayoutEngine xkb_keycode_t xkb_keycode, xkb_mod_mask_t xkb_flags, xkb_keysym_t xkb_keysym, - base::char16 character) const; + char16_t character) const; // Sets a new XKB keymap. This updates xkb_state_ (which takes ownership // of the keymap), and updates xkb_flag_map_ for the new keymap. @@ -125,10 +124,10 @@ class COMPONENT_EXPORT(EVENTS_OZONE_LAYOUT) XkbKeyboardLayoutEngine // Helper for difficult VKEY lookup. If |ui_flags| matches |base_flags|, // returns |base_character|; otherwise returns the XKB character for // the keycode and mapped |ui_flags|. - base::char16 XkbSubCharacter(xkb_keycode_t xkb_keycode, - xkb_mod_mask_t base_flags, - base::char16 base_character, - xkb_mod_mask_t flags) const; + char16_t XkbSubCharacter(xkb_keycode_t xkb_keycode, + xkb_mod_mask_t base_flags, + char16_t base_character, + xkb_mod_mask_t flags) const; // Callback when keymap file is loaded complete. void OnKeymapLoaded(const std::string& layout_name, 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 1d034ef053a..803624e289c 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 @@ -38,16 +38,16 @@ class VkTestXkbKeyboardLayoutEngine : public XkbKeyboardLayoutEngine { public: enum class EntryType { NONE, PRINTABLE, KEYSYM }; struct PrintableEntry { - base::char16 plain_character; - base::char16 shift_character; - base::char16 altgr_character; + char16_t plain_character; + char16_t shift_character; + char16_t altgr_character; DomCode dom_code; }; struct KeysymEntry { DomCode dom_code; int flags; xkb_keysym_t keysym; - base::char16 character; + char16_t character; }; struct RuleNames { @@ -86,13 +86,11 @@ class VkTestXkbKeyboardLayoutEngine : public XkbKeyboardLayoutEngine { keysym_entry_ = entry; } - xkb_keysym_t CharacterToKeySym(base::char16 c) const { - return 0x01000000u + c; - } + xkb_keysym_t CharacterToKeySym(char16_t c) const { return 0x01000000u + c; } KeyboardCode GetKeyboardCode(DomCode dom_code, int flags, - base::char16 character) const { + char16_t character) const { KeyboardCode key_code = DifficultKeyboardCode( dom_code, flags, key_code_converter_.DomCodeToXkbKeyCode(dom_code), flags, CharacterToKeySym(character), character); diff --git a/chromium/ui/events/platform/x11/x11_hotplug_event_handler.cc b/chromium/ui/events/platform/x11/x11_hotplug_event_handler.cc index d70361932b6..d2880d8b820 100644 --- a/chromium/ui/events/platform/x11/x11_hotplug_event_handler.cc +++ b/chromium/ui/events/platform/x11/x11_hotplug_event_handler.cc @@ -408,15 +408,26 @@ void X11HotplugEventHandler::OnHotplugEvent() { if (id >= kMaxDeviceNum) continue; + // In XWayland, physical devices are not exposed to X Server, but + // rather X11 and Wayland uses wayland protocol to communicate + // devices. + + // So, xinput that Chromium uses to enumerate devices prepends + // "xwayland-" to each device name. Though, Wayland doesn't expose TOUCHPAD + // directly. Instead, it's part of xwayland-pointer. x11::Atom type = device.device_type; - if (type == x11::GetAtom("KEYBOARD")) + if (type == x11::GetAtom("KEYBOARD") || + type == x11::GetAtom("xwayland-keyboard")) { device_types[id] = DEVICE_TYPE_KEYBOARD; - else if (type == x11::GetAtom("MOUSE")) + } else if (type == x11::GetAtom("MOUSE") || + type == x11::GetAtom("xwayland-pointer")) { device_types[id] = DEVICE_TYPE_MOUSE; - else if (type == x11::GetAtom("TOUCHPAD")) + } else if (type == x11::GetAtom("TOUCHPAD")) { device_types[id] = DEVICE_TYPE_TOUCHPAD; - else if (type == x11::GetAtom("TOUCHSCREEN")) + } else if (type == x11::GetAtom("TOUCHSCREEN") || + type == x11::GetAtom("xwayland-touch")) { device_types[id] = DEVICE_TYPE_TOUCHSCREEN; + } } std::vector device_infos; diff --git a/chromium/ui/events/win/events_win_utils.h b/chromium/ui/events/win/events_win_utils.h index e463ac82463..503fb5ee0e4 100644 --- a/chromium/ui/events/win/events_win_utils.h +++ b/chromium/ui/events/win/events_win_utils.h @@ -9,8 +9,8 @@ #include #include +#include -#include "base/strings/string16.h" #include "build/build_config.h" #include "ui/display/display.h" #include "ui/events/event.h" @@ -101,8 +101,6 @@ bool GetFlingData(const MSG& native_event, // scrolled. bool GetScrollOffsetsFromMSG(const MSG& native_event); -void ComputeEventLatencyOSFromMSG(const MSG& native_event); - } // namespace ui #endif // UI_EVENTS_WIN_EVENTS_WIN_UTILS_H_ diff --git a/chromium/ui/events/x/x11_event_translation.cc b/chromium/ui/events/x/x11_event_translation.cc index 0858b17540b..005dbd697ef 100644 --- a/chromium/ui/events/x/x11_event_translation.cc +++ b/chromium/ui/events/x/x11_event_translation.cc @@ -66,11 +66,11 @@ Event::Properties GetEventPropertiesFromXEvent(EventType type, uint8_t hw_keycode = static_cast(key->detail); properties.emplace(kPropertyKeyboardHwKeyCode, Values{hw_keycode}); - // IBus-gtk specific flags - uint8_t ibus_flags = (state >> kPropertyKeyboardIBusFlagOffset) & - kPropertyKeyboardIBusFlagMask; - if (ibus_flags) - properties.emplace(kPropertyKeyboardIBusFlag, Values{ibus_flags}); + // IBus-/fctix-GTK specific flags + uint8_t ime_flags = (state >> kPropertyKeyboardImeFlagOffset) & + kPropertyKeyboardImeFlagMask; + if (ime_flags) + properties.emplace(kPropertyKeyboardImeFlag, Values{ime_flags}); } else if (type == ET_MOUSE_EXITED) { // NotifyVirtual events are created for intermediate windows that the diff --git a/chromium/ui/file_manager/BUILD.gn b/chromium/ui/file_manager/BUILD.gn index 70f3a083ae2..ab2966fcb9c 100644 --- a/chromium/ui/file_manager/BUILD.gn +++ b/chromium/ui/file_manager/BUILD.gn @@ -37,14 +37,13 @@ group("closure_compile") { deps = [ "audio_player/elements:closure_compile", "audio_player/js:closure_compile", - "base/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", "file_manager/foreground/js/ui:closure_compile", - "file_manager/test:closure_compile", "gallery/js:closure_compile", "gallery/js/image_editor:closure_compile", "image_loader:closure_compile", @@ -57,7 +56,6 @@ group("closure_compile") { group("unit_test_data") { testonly = true deps = [ - "base/js:js_test_gen_html", "file_manager/background/js:js_test_gen_html_modules", "file_manager/common/js:js_test_gen_html_modules", "file_manager/foreground/elements:js_test_gen_html_modules", @@ -80,6 +78,7 @@ preprocess_folder = "$target_gen_dir/preprocessed" preprocess_if_expr("preprocess_static") { in_folder = "./" out_folder = preprocess_folder + out_manifest = "$target_gen_dir/manifest_preprocess_static.json" in_files = [ "audio_player/js/main.m.js", @@ -109,6 +108,7 @@ preprocess_if_expr("preprocess_static") { preprocess_if_expr("preprocess_generated") { in_folder = target_gen_dir out_folder = preprocess_folder + out_manifest = "$target_gen_dir/manifest_preprocess_generated.json" in_files = [ # Audio Player: @@ -123,52 +123,54 @@ preprocess_if_expr("preprocess_generated") { "audio_player/elements/control_panel.m.js", "audio_player/elements/repeat_button.m.js", - # Base: - "base/js/app_util.m.js", - "base/js/error_counter.m.js", - "base/js/filtered_volume_manager.m.js", - "base/js/mediasession_types.m.js", - "base/js/volume_manager_types.m.js", - # Common: + "file_manager/common/js/app_util.m.js", "file_manager/common/js/async_util.m.js", + "file_manager/common/js/error_counter.m.js", "file_manager/common/js/file_operation_common.m.js", "file_manager/common/js/file_type.m.js", "file_manager/common/js/files_app_entry_types.m.js", + "file_manager/common/js/filtered_volume_manager.m.js", "file_manager/common/js/importer_common.m.js", "file_manager/common/js/lru_cache.m.js", + "file_manager/common/js/mediasession_types.m.js", "file_manager/common/js/metrics.m.js", "file_manager/common/js/metrics_base.m.js", + "file_manager/common/js/mock_chrome.m.js", + "file_manager/common/js/power.m.js", "file_manager/common/js/progress_center_common.m.js", "file_manager/common/js/storage_adapter.m.js", + "file_manager/common/js/test_error_reporting.m.js", "file_manager/common/js/trash.m.js", "file_manager/common/js/util.m.js", + "file_manager/common/js/volume_manager_types.m.js", + "file_manager/common/js/xfm.m.js", # Externs: - "externs/background/background_base.m.js", - "externs/background/crostini.m.js", - "externs/background/drive_sync_handler.m.js", - "externs/background/duplicate_finder.m.js", - "externs/background/file_browser_background_full.m.js", - "externs/background/file_operation_manager.m.js", - "externs/background/import_history.m.js", - "externs/background/media_import_handler.m.js", - "externs/background/media_scanner.m.js", - "externs/background/progress_center.m.js", - "externs/background/task_queue.m.js", - "externs/background_window.m.js", - "externs/command_handler_deps.m.js", - "externs/directory_change_event.m.js", - "externs/drive_dialog_controller.m.js", - "externs/entry_location.m.js", - "externs/entries_changed_event.m.js", - "externs/exif_entry.m.js", - "externs/files_app_entry_interfaces.m.js", - "externs/metadata_worker_window.m.js", - "externs/progress_center_panel.m.js", - "externs/volume_info.m.js", - "externs/volume_info_list.m.js", - "externs/volume_manager.m.js", + "file_manager/externs/background/background_base.m.js", + "file_manager/externs/background/crostini.m.js", + "file_manager/externs/background/drive_sync_handler.m.js", + "file_manager/externs/background/duplicate_finder.m.js", + "file_manager/externs/background/file_browser_background_full.m.js", + "file_manager/externs/background/file_operation_manager.m.js", + "file_manager/externs/background/import_history.m.js", + "file_manager/externs/background/media_import_handler.m.js", + "file_manager/externs/background/media_scanner.m.js", + "file_manager/externs/background/progress_center.m.js", + "file_manager/externs/background/task_queue.m.js", + "file_manager/externs/background_window.m.js", + "file_manager/externs/command_handler_deps.m.js", + "file_manager/externs/directory_change_event.m.js", + "file_manager/externs/drive_dialog_controller.m.js", + "file_manager/externs/entry_location.m.js", + "file_manager/externs/entries_changed_event.m.js", + "file_manager/externs/exif_entry.m.js", + "file_manager/externs/files_app_entry_interfaces.m.js", + "file_manager/externs/metadata_worker_window.m.js", + "file_manager/externs/progress_center_panel.m.js", + "file_manager/externs/volume_info.m.js", + "file_manager/externs/volume_info_list.m.js", + "file_manager/externs/volume_manager.m.js", # Files app Background: "file_manager/background/js/app_window_wrapper.m.js", @@ -373,13 +375,12 @@ preprocess_if_expr("preprocess_generated") { deps = [ "//ui/file_manager/audio_player/elements:elements", "//ui/file_manager/audio_player/js:modulize", - "//ui/file_manager/base/js:modulize", - "//ui/file_manager/externs:modulize", - "//ui/file_manager/externs/background: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/js:modulize", @@ -397,65 +398,102 @@ generated_grd = "$target_gen_dir/${grd_prefix}_resources.grd" generate_grd("build_grd") { out_grd = generated_grd + grdp_files = [ + "$target_gen_dir/audio_player/static_resources.grdp", + "$target_gen_dir/file_manager/static_resources.grdp", + ] + + deps = [ + ":preprocess_generated", + "audio_player:build_static_grdp", + "file_manager:build_static_grdp", + "//ui/file_manager/audio_player/js:build", + "//ui/file_manager/audio_player/js:build_background", + "//ui/file_manager/audio_player/js:build_worker", + "//ui/file_manager/file_manager:fix_broken_images", + ] + input_files_base_dir = rebase_path(target_gen_dir, root_build_dir) input_files = [ "audio_player/js/main.m.rollup.js", "audio_player/js/main_background.m.rollup.js", "audio_player/js/metadata_worker.m.rollup.js", - "image_loader/background.m.rollup.js", - # Fix broken images: "file_manager/images/files/ui/arrow_right.svg", "file_manager/images/files/ui/menu_ng.svg", - "file_manager/background/js/main_background.m.rollup.js", - "file_manager/foreground/elements/files_icon_button.m.js", - "file_manager/foreground/elements/files_ripple.m.js", - "file_manager/foreground/elements/files_toggle_ripple.m.js", - "file_manager/foreground/js/deferred_elements.m.rollup.js", - "file_manager/foreground/js/main.m.rollup.js", - "file_manager/foreground/js/metadata_dispatcher.m.rollup.js", - "file_manager/foreground/js/shared.m.rollup.js", "file_manager/main_modules.html", - - "video_player/js/main.m.rollup.js", - "video_player/js/main_background.m.rollup.js", ] resource_path_rewrites = [ "audio_player/js/main.m.rollup.js|audio_player/js/main.m.js", "audio_player/js/main_background.m.rollup.js|audio_player/js/main_background.m.js", "audio_player/js/metadata_worker.m.rollup.js|audio_player/js/metadata_worker.m.js", - "image_loader/background.m.rollup.js|image_loader/background.m.js", - "file_manager/background/js/main_background.m.rollup.js|file_manager/background/js/main_background.m.js", - "file_manager/foreground/js/deferred_elements.m.rollup.js|file_manager/foreground/js/deferred_elements.m.js", - "file_manager/foreground/js/main.m.rollup.js|file_manager/foreground/js/main.m.js", - "file_manager/foreground/js/metadata_dispatcher.m.rollup.js|file_manager/foreground/js/metadata_dispatcher.m.js", - "video_player/js/main.m.rollup.js|video_player/js/main.m.js", - "video_player/js/main_background.m.rollup.js|video_player/js/main_background.m.js", ] - grdp_files = [ - "$target_gen_dir/audio_player/static_resources.grdp", - "$target_gen_dir/file_manager/static_resources.grdp", - ] - - deps = [ - "audio_player:build_static_grdp", - "file_manager:build_static_grdp", - "//ui/file_manager/audio_player/js:build", - "//ui/file_manager/audio_player/js:build_background", - "//ui/file_manager/audio_player/js:build_worker", - "//ui/file_manager/file_manager:fix_broken_images", - "//ui/file_manager/file_manager/background/js:build", - "//ui/file_manager/file_manager/foreground/elements:elements", - "//ui/file_manager/file_manager/foreground/js:build", - "//ui/file_manager/file_manager/foreground/js:build_worker", - "//ui/file_manager/image_loader:build", - "//ui/file_manager/video_player/js:build", - "//ui/file_manager/video_player/js:build_background", - ] + if (optimize_webui) { + input_files += [ + # Fix unittestxs: These files are imported via chrome-extension:// URLs: + "file_manager/common/js/app_util.m.js", + "file_manager/common/js/file_type.m.js", + "file_manager/common/js/files_app_entry_types.m.js", + "file_manager/common/js/lru_cache.m.js", + "file_manager/common/js/mock_chrome.m.js", + "file_manager/common/js/power.m.js", + "file_manager/common/js/storage_adapter.m.js", + "file_manager/common/js/test_error_reporting.m.js", + "file_manager/common/js/volume_manager_types.m.js", + "file_manager/common/js/xfm.m.js", + "file_manager/externs/background/background_base.m.js", + "file_manager/externs/entry_location.m.js", + "file_manager/externs/files_app_entry_interfaces.m.js", + "file_manager/externs/volume_info.m.js", + "file_manager/externs/volume_info_list.m.js", + "file_manager/externs/volume_manager.m.js", + "file_manager/foreground/js/metadata/image_orientation.m.js", + "image_loader/image_loader_client.m.js", + "image_loader/load_image_request.m.js", + + "file_manager/background/js/main_background.m.rollup.js", + "file_manager/foreground/js/deferred_elements.m.rollup.js", + "file_manager/foreground/js/main.m.rollup.js", + "file_manager/foreground/js/metadata_dispatcher.m.rollup.js", + "file_manager/foreground/js/shared.m.rollup.js", + + "image_loader/background.m.rollup.js", + "video_player/js/main.m.rollup.js", + "video_player/js/main_background.m.rollup.js", + ] + + resource_path_rewrites += [ + "file_manager/background/js/main_background.m.rollup.js|file_manager/background/js/main_background.m.js", + "file_manager/foreground/js/deferred_elements.m.rollup.js|file_manager/foreground/js/deferred_elements.m.js", + "file_manager/foreground/js/main.m.rollup.js|file_manager/foreground/js/main.m.js", + "file_manager/foreground/js/metadata_dispatcher.m.rollup.js|file_manager/foreground/js/metadata/metadata_dispatcher.m.js", + + "image_loader/background.m.rollup.js|image_loader/background.m.js", + "video_player/js/main.m.rollup.js|video_player/js/main.m.js", + "video_player/js/main_background.m.rollup.js|video_player/js/main_background.m.js", + ] + + deps += [ + "//ui/file_manager/file_manager/background/js:build", + "//ui/file_manager/file_manager/foreground/elements:elements", + "//ui/file_manager/file_manager/foreground/js:build", + "//ui/file_manager/file_manager/foreground/js:build_worker", + "//ui/file_manager/image_loader:build", + "//ui/file_manager/video_player/js:build", + "//ui/file_manager/video_player/js:build_background", + ] + } else { + manifest_files = [ + "$target_gen_dir/manifest_preprocess_generated.json", + "$target_gen_dir/manifest_preprocess_static.json", + ] + + deps += [ ":preprocess_static" ] + } } # Resources for the JS modules. diff --git a/chromium/ui/file_manager/audio_player/elements/BUILD.gn b/chromium/ui/file_manager/audio_player/elements/BUILD.gn index f9a97403560..24316d2fe7c 100644 --- a/chromium/ui/file_manager/audio_player/elements/BUILD.gn +++ b/chromium/ui/file_manager/audio_player/elements/BUILD.gn @@ -90,7 +90,6 @@ js_library("control_panel.m") { ] deps = [ ":repeat_button.m", - "//third_party/polymer/v3_0/components-chromium/font-roboto:roboto", "//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", @@ -121,7 +120,6 @@ js_library("track_info_panel.m") { "$root_gen_dir/ui/file_manager/audio_player/elements/track_info_panel.m.js", ] deps = [ - "//third_party/polymer/v3_0/components-chromium/font-roboto:roboto", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_button:cr_button.m", ] @@ -142,7 +140,6 @@ 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/font-roboto:roboto", "//third_party/polymer/v3_0/components-chromium/paper-ripple:paper-ripple", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] diff --git a/chromium/ui/file_manager/audio_player/js/BUILD.gn b/chromium/ui/file_manager/audio_player/js/BUILD.gn index c47dae2b016..1f293830555 100644 --- a/chromium/ui/file_manager/audio_player/js/BUILD.gn +++ b/chromium/ui/file_manager/audio_player/js/BUILD.gn @@ -36,7 +36,12 @@ js_type_check("closure_compile_jsmodules") { js_type_check("closure_compile_polymer") { is_polymer3 = true - closure_flags = default_closure_args + [ "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=../../ui/file_manager/file_manager/\"" ] + closure_flags = default_closure_args + [ + "js_module_root=gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + ] + deps = [ ":audio_player.m", ":main.m", @@ -48,8 +53,8 @@ js_library("closure_compile_externs") { externs_list = [ "$externs_path/chrome_extensions.js", "$externs_path/mediasession.js", - "//ui/file_manager/externs/audio_player_foreground.js", - "//ui/file_manager/externs/platform.js", + "//ui/file_manager/file_manager/externs/audio_player_foreground.js", + "//ui/file_manager/file_manager/externs/platform.js", ] } @@ -57,9 +62,9 @@ js_library("audio_player") { deps = [ "//ui/file_manager/audio_player/elements:audio_player", "//ui/file_manager/audio_player/elements:track_list", - "//ui/file_manager/base/js:app_util", - "//ui/file_manager/base/js:filtered_volume_manager", - "//ui/file_manager/base/js:mediasession_types", + "//ui/file_manager/file_manager/common/js:app_util", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager", + "//ui/file_manager/file_manager/common/js:mediasession_types", "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/foreground/js/metadata:content_metadata_provider", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model", @@ -72,20 +77,20 @@ js_library("audio_player.m") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/file_manager/audio_player/elements:audio_player.m", - "//ui/file_manager/base/js:app_util.m", - "//ui/file_manager/base/js:filtered_volume_manager.m", - "//ui/file_manager/base/js:mediasession_types.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", + "//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", + "//ui/file_manager/file_manager/common/js:mediasession_types.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/foreground/js/metadata:content_metadata_provider.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", "//ui/webui/resources/js:load_time_data", ] externs_list = [ - "//ui/file_manager/externs/audio_player_foreground.js", + "//ui/file_manager/file_manager/externs/audio_player_foreground.js", "$externs_path/mediasession.js", ] @@ -179,6 +184,12 @@ preprocess_folder = rebase_path("$target_gen_dir/../../preprocessed/audio_player/js", root_build_dir) +files_app_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/file_manager", + root_build_dir) +image_loader_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/image_loader", + root_build_dir) optimize_webui("build") { host = "audio_player" @@ -187,6 +198,11 @@ optimize_webui("build") { js_out_files = [ "main.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":main.m", "//ui/file_manager:preprocess_generated", @@ -203,6 +219,11 @@ optimize_webui("build_worker") { js_out_files = [ "metadata_worker.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":metadata_worker.m", "//ui/file_manager:preprocess_generated", @@ -219,6 +240,11 @@ optimize_webui("build_background") { js_out_files = [ "main_background.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":main_background.m", "//ui/file_manager:preprocess_generated", diff --git a/chromium/ui/file_manager/base/js/BUILD.gn b/chromium/ui/file_manager/base/js/BUILD.gn index c60eeb677a1..e69de29bb2d 100644 --- a/chromium/ui/file_manager/base/js/BUILD.gn +++ b/chromium/ui/file_manager/base/js/BUILD.gn @@ -1,213 +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("//third_party/closure_compiler/js_unit_tests.gni") -import("//ui/file_manager/base/gn/js_test_gen_html.gni") -import("//ui/webui/resources/js/cr.gni") -import("//ui/webui/resources/tools/js_modulizer.gni") - -visibility = [ "//ui/file_manager/*" ] - -group("closure_compile") { - testonly = true - deps = [ - ":closure_compile_jsmodules", - ":closure_compile_module", - ":js_test_gen_html_type_check_auto", - ":test_support_type_check", - ":test_support_type_check_jsmodules", - ] -} - -js_type_check("closure_compile_jsmodules") { - deps = [ - ":app_util.m", - ":error_counter.m", - ":filtered_volume_manager.m", - ":volume_manager_types.m", - ] - - closure_flags = strict_error_checking_closure_args + [ - "js_module_root=./gen/ui/", - "js_module_root=../../ui/", - ] -} - -js_type_check("closure_compile_module") { - uses_legacy_modules = true - deps = [ - ":app_util", - ":error_counter", - ":filtered_volume_manager", - ] -} - -js_type_check("test_support_type_check") { - testonly = true - deps = [ - ":mock_chrome", - ":test_error_reporting", - ] -} - -js_type_check("test_support_type_check_jsmodules") { - testonly = true - deps = [ - ":mock_chrome.m", - ":test_error_reporting.m", - ] -} - -js_library("app_util") { - deps = [ - ":volume_manager_types", - "//ui/file_manager/externs:volume_manager", - ] - externs_list = [ - "//ui/file_manager/externs/app_window_common.js", - "//ui/file_manager/externs/background/background_base.js", - ] -} - -js_library("app_util.m") { - sources = [ "$root_gen_dir/ui/file_manager/base/js/app_util.m.js" ] - deps = [ - "//ui/file_manager/externs:file_manager_private", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:background_base.m", - ] - externs_list = [ "//ui/file_manager/externs/app_window_common.js" ] - - extra_deps = [ ":modulize" ] -} - -js_library("error_counter") { -} - -js_library("error_counter.m") { - sources = [ "$root_gen_dir/ui/file_manager/base/js/error_counter.m.js" ] - - extra_deps = [ ":modulize" ] -} - -js_library("filtered_volume_manager") { - deps = [ - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:file_manager_private", - "//ui/file_manager/externs:volume_manager", - "//ui/file_manager/file_manager/common/js:async_util", - "//ui/file_manager/file_manager/common/js:files_app_entry_types", - "//ui/webui/resources/js:cr", - "//ui/webui/resources/js/cr/ui:array_data_model", - ] - externs_list = - [ "//ui/file_manager/externs/background/volume_manager_factory.js" ] -} - -js_library("filtered_volume_manager.m") { - sources = - [ "$root_gen_dir/ui/file_manager/base/js/filtered_volume_manager.m.js" ] - deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_info_list.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", - "//ui/webui/resources/js:assert.m", - "//ui/webui/resources/js:cr.m", - "//ui/webui/resources/js/cr:event_target.m", - "//ui/webui/resources/js/cr/ui:array_data_model.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("mock_chrome") { - testonly = true -} - -js_library("mock_chrome.m") { - testonly = true - sources = [ "$root_gen_dir/ui/file_manager/base/js/mock_chrome.m.js" ] - - extra_deps = [ ":modulize" ] -} - -js_library("test_error_reporting") { - testonly = true - deps = [ - # Note we allow targets depending on test_error_reporting to access - # webui_resource_test transitively. - "//ui/webui/resources/js:webui_resource_test", - ] -} - -js_library("test_error_reporting.m") { - testonly = true - sources = - [ "$root_gen_dir/ui/file_manager/base/js/test_error_reporting.m.js" ] - - extra_deps = [ ":modulize" ] -} - -js_library("volume_manager_types") { - deps = [ - "//ui/file_manager/externs:file_manager_private", - "//ui/webui/resources/js:assert", - ] -} - -js_unittest("volume_manager_types_unittest.m") { - deps = [ ":volume_manager_types.m" ] -} - -js_library("volume_manager_types.m") { - sources = - [ "$root_gen_dir/ui/file_manager/base/js/volume_manager_types.m.js" ] - - deps = [ - "//ui/file_manager/externs:file_manager_private", - "//ui/webui/resources/js:assert.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_test_gen_html("js_test_gen_html") { - deps = [ ":volume_manager_types_unittest.m" ] - js_module = true - - closure_flags = - strict_error_checking_closure_args + [ - "js_module_root=./gen/ui/file_manager/base/js", - "js_module_root=../../ui/file_manager/base/js", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", - ] -} - -js_library("mediasession_types") { -} - -js_library("mediasession_types.m") { - sources = [ "$root_gen_dir/ui/file_manager/base/js/mediasession_types.m.js" ] - - extra_deps = [ ":modulize" ] -} - -js_modulizer("modulize") { - input_files = [ - "app_util.js", - "filtered_volume_manager.js", - "mediasession_types.js", - "mock_chrome.js", - "test_error_reporting.js", - "volume_manager_types.js", - "error_counter.js", - ] - - namespace_rewrites = cr_namespace_rewrites -} diff --git a/chromium/ui/file_manager/base/tools/tests/empty_dependency_list_expected.gn b/chromium/ui/file_manager/base/tools/tests/empty_dependency_list_expected.gn index 6538a5492e9..00082264ffb 100644 --- a/chromium/ui/file_manager/base/tools/tests/empty_dependency_list_expected.gn +++ b/chromium/ui/file_manager/base/tools/tests/empty_dependency_list_expected.gn @@ -1,6 +1,6 @@ js_unittest("importer_common_unittest.m") { deps = [ - "//ui/file_manager/base/js:mock_chrome", + "//ui/file_manager/file_manager/common/js:mock_chrome", ] } diff --git a/chromium/ui/file_manager/base/tools/tests/single_line_dependency_list_expected.gn b/chromium/ui/file_manager/base/tools/tests/single_line_dependency_list_expected.gn index ee0eadde89f..ee97ecb976c 100644 --- a/chromium/ui/file_manager/base/tools/tests/single_line_dependency_list_expected.gn +++ b/chromium/ui/file_manager/base/tools/tests/single_line_dependency_list_expected.gn @@ -1,7 +1,7 @@ js_unittest("importer_common_unittest.m") { deps = [ - "//ui/file_manager/base/js:mock_chrome", + "//ui/file_manager/file_manager/common/js:mock_chrome", ":mock_entry", ] } diff --git a/chromium/ui/file_manager/externs/BUILD.gn b/chromium/ui/file_manager/externs/BUILD.gn deleted file mode 100644 index 7d53f228b52..00000000000 --- a/chromium/ui/file_manager/externs/BUILD.gn +++ /dev/null @@ -1,190 +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/tools/js_modulizer.gni") - -js_library("file_manager_private") { - sources = [] - - # The file_manager_private extern depends on file_system_provider and - # extension APIs. Ensure they're pulled in together. - externs_list = [ - "$externs_path/chrome.js", - "$externs_path/chrome_extensions.js", - "$externs_path/file_manager_private.js", - "$externs_path/file_system_provider.js", - ] -} - -js_library("background_window.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/background_window.m.js" ] - - deps = [ "//ui/file_manager/externs/background:background_base.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("command_handler_deps.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/command_handler_deps.m.js" ] - deps = [ - ":files_app_entry_interfaces.m", - ":volume_manager.m", - "background:crostini.m", - "background:file_operation_manager.m", - "background:progress_center.m", - "//ui/file_manager/file_manager/foreground/js:actions_controller.m", - "//ui/file_manager/file_manager/foreground/js:dialog_type.m", - "//ui/file_manager/file_manager/foreground/js:directory_contents.m", - "//ui/file_manager/file_manager/foreground/js:directory_model.m", - "//ui/file_manager/file_manager/foreground/js:directory_tree_naming_controller.m", - "//ui/file_manager/file_manager/foreground/js:file_selection.m", - "//ui/file_manager/file_manager/foreground/js:file_transfer_controller.m", - "//ui/file_manager/file_manager/foreground/js:naming_controller.m", - "//ui/file_manager/file_manager/foreground/js:providers_model.m", - "//ui/file_manager/file_manager/foreground/js:spinner_controller.m", - "//ui/file_manager/file_manager/foreground/js:task_controller.m", - "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", - "//ui/file_manager/file_manager/foreground/js/ui:directory_tree.m", - "//ui/file_manager/file_manager/foreground/js/ui:file_manager_ui.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("directory_change_event.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/directory_change_event.m.js" ] - deps = [ ":files_app_entry_interfaces.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("drive_dialog_controller.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/drive_dialog_controller.m.js" ] - - extra_deps = [ ":modulize" ] -} - -js_library("entries_changed_event.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/entries_changed_event.m.js" ] - - deps = [ "//ui/file_manager/file_manager/common/js:util.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("entry_location.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/entry_location.m.js" ] - - deps = [ - ":volume_info.m", - "//ui/file_manager/base/js:volume_manager_types.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("exif_entry.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/exif_entry.m.js" ] - - deps = [ - "//ui/file_manager/file_manager/foreground/js/metadata:exif_constants.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("files_app_entry_interfaces.m") { - sources = [ - "$root_gen_dir/ui/file_manager/externs/files_app_entry_interfaces.m.js", - ] - - deps = [ "//ui/file_manager/base/js:volume_manager_types.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("metadata_worker_window.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/metadata_worker_window.m.js" ] - - extra_deps = [ ":modulize" ] -} - -js_library("progress_center_panel.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/progress_center_panel.m.js" ] - - deps = [ "//ui/file_manager/file_manager/common/js:progress_center_common.m" ] - extra_deps = [ ":modulize" ] -} - -js_library("volume_manager") { - sources = [] - - # Encapsulate volume_manager.js and its dependencies. Note this should really - # depend on volume_manager_types.js as well, but that's not an extern. - externs_list = [ - "entry_location.js", - "files_app_entry_interfaces.js", - "volume_info.js", - "volume_info_list.js", - "volume_manager.js", - ] -} - -js_library("volume_manager.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/volume_manager.m.js" ] - - deps = [ - ":entry_location.m", - ":files_app_entry_interfaces.m", - ":volume_info.m", - ":volume_info_list.m", - "//ui/file_manager/base/js:volume_manager_types.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("volume_info.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/volume_info.m.js" ] - - deps = [ - ":files_app_entry_interfaces.m", - "//ui/file_manager/base/js:volume_manager_types.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("volume_info_list.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/volume_info_list.m.js" ] - - deps = [ ":volume_info.m" ] - - extra_deps = [ ":modulize" ] -} - -js_modulizer("modulize") { - input_files = [ - "background_window.js", - "command_handler_deps.js", - "directory_change_event.js", - "drive_dialog_controller.js", - "entries_changed_event.js", - "entry_location.js", - "exif_entry.js", - "files_app_entry_interfaces.js", - "metadata_worker_window.js", - "progress_center_panel.js", - "volume_info.js", - "volume_info_list.js", - "volume_manager.js", - ] -} diff --git a/chromium/ui/file_manager/externs/background/BUILD.gn b/chromium/ui/file_manager/externs/background/BUILD.gn deleted file mode 100644 index a8485738a66..00000000000 --- a/chromium/ui/file_manager/externs/background/BUILD.gn +++ /dev/null @@ -1,158 +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("//third_party/closure_compiler/compile_js.gni") -import("//ui/webui/resources/tools/js_modulizer.gni") - -js_library("file_browser_background_full") { - sources = [] - - externs_list = [ - "background_base.js", - "crostini.js", - "../drive_dialog_controller.js", - "drive_sync_handler.js", - "duplicate_finder.js", - "file_browser_background_full.js", - "file_operation_manager.js", - "import_history.js", - "media_import_handler.js", - "media_scanner.js", - "progress_center.js", - "../progress_center_panel.js", - "task_queue.js", - ] -} - -js_library("file_browser_background_full.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/background/file_browser_background_full.m.js" ] - deps = [ - ":background_base.m", - ":crostini.m", - ":drive_sync_handler.m", - ":file_operation_manager.m", - ":import_history.m", - ":media_import_handler.m", - ":media_scanner.m", - ":progress_center.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("background_base.m") { - sources = [ - "$root_gen_dir/ui/file_manager/externs/background/background_base.m.js", - ] - - deps = [ "..:volume_manager.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("drive_sync_handler.m") { - sources = [ - "$root_gen_dir/ui/file_manager/externs/background/drive_sync_handler.m.js", - ] - - deps = [ "..:drive_dialog_controller.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("duplicate_finder.m") { - sources = [ - "$root_gen_dir/ui/file_manager/externs/background/duplicate_finder.m.js", - ] - deps = [ - ":import_history.m", - "//ui/file_manager/file_manager/common/js:importer_common.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("crostini.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/background/crostini.m.js" ] - deps = [ "..:volume_manager.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("file_operation_manager.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/background/file_operation_manager.m.js" ] - deps = [ - "..:files_app_entry_interfaces.m", - "..:volume_manager.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("import_history.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/background/import_history.m.js" ] - deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("media_import_handler.m") { - sources = [ "$root_gen_dir/ui/file_manager/externs/background/media_import_handler.m.js" ] - deps = [ - ":drive_sync_handler.m", - ":duplicate_finder.m", - ":import_history.m", - ":media_scanner.m", - ":progress_center.m", - ":task_queue.m", - "//ui/file_manager/file_manager/common/js:importer_common.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("media_scanner.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/background/media_scanner.m.js" ] - deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] - - extra_deps = [ ":modulize" ] -} - -js_library("progress_center.m") { - sources = [ - "$root_gen_dir/ui/file_manager/externs/background/progress_center.m.js", - ] - deps = [ - "..:progress_center_panel.m", - "//ui/file_manager/file_manager/common/js:progress_center_common.m", - ] - - extra_deps = [ ":modulize" ] -} - -js_library("task_queue.m") { - sources = - [ "$root_gen_dir/ui/file_manager/externs/background/task_queue.m.js" ] - deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] - - extra_deps = [ ":modulize" ] -} - -js_modulizer("modulize") { - input_files = [ - "file_browser_background_full.js", - "background_base.js", - "crostini.js", - "drive_sync_handler.js", - "duplicate_finder.js", - "file_operation_manager.js", - "import_history.js", - "media_import_handler.js", - "media_scanner.js", - "progress_center.js", - "task_queue.js", - ] -} diff --git a/chromium/ui/file_manager/file_manager/BUILD.gn b/chromium/ui/file_manager/file_manager/BUILD.gn index 8a8a131f088..88000807f62 100644 --- a/chromium/ui/file_manager/file_manager/BUILD.gn +++ b/chromium/ui/file_manager/file_manager/BUILD.gn @@ -74,6 +74,7 @@ generate_grd("build_static_grdp") { "foreground/images/files/ui/delete.svg", "foreground/images/files/ui/delete_ng.svg", "foreground/images/files/ui/drive_logo.svg", + "foreground/images/files/ui/photos_logo.svg", "foreground/images/files/ui/external_link.svg", "foreground/images/files/ui/filetype_placeholder_audio.png", "foreground/images/files/ui/2x/filetype_placeholder_audio.png", 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 86bbc354e0b..d1328dc499b 100644 --- a/chromium/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/chromium/ui/file_manager/file_manager/background/js/BUILD.gn @@ -151,23 +151,23 @@ js_library("closure_compile_externs") { sources = [] externs_list = [ "$externs_path/metrics_private.js", - "//ui/file_manager/externs/background/crostini.js", - "//ui/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/externs/background/background_base.js", - "//ui/file_manager/externs/background/file_browser_background_full.js", - "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/background/import_history.js", - "//ui/file_manager/externs/background/media_import_handler.js", - "//ui/file_manager/externs/background/media_scanner.js", - "//ui/file_manager/externs/background/progress_center.js", - "//ui/file_manager/externs/background_window.js", - "//ui/file_manager/externs/css_rule.js", - "//ui/file_manager/externs/drive_dialog_controller.js", - "//ui/file_manager/externs/launcher_search_provider.js", - "//ui/file_manager/externs/platform.js", - "//ui/file_manager/externs/progress_center_panel.js", - "//ui/file_manager/externs/background/task_queue.js", - "//ui/file_manager/externs/background/duplicate_finder.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/import_history.js", + "//ui/file_manager/file_manager/externs/background/media_import_handler.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/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", + "//ui/file_manager/file_manager/externs/background/duplicate_finder.js", ] } @@ -175,7 +175,7 @@ js_library("app_window_wrapper") { visibility += related_apps deps = [ ":app_windows", - "//ui/file_manager/base/js:app_util", + "//ui/file_manager/file_manager/common/js:app_util", "//ui/file_manager/file_manager/common/js:async_util", ] } @@ -185,7 +185,7 @@ js_library("app_window_wrapper.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/app_window_wrapper.m.js" ] deps = [ ":app_windows.m", - "//ui/file_manager/base/js:app_util.m", + "//ui/file_manager/file_manager/common/js:app_util.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/webui/resources/js:assert.m", ] @@ -221,10 +221,10 @@ js_library("background") { ":mount_metrics", ":progress_center", ":trash", - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:files_app_entry_types", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } @@ -249,21 +249,21 @@ js_library("background.m") { ":mount_metrics.m", ":progress_center.m", ":volume_manager_factory.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:crostini.m", - "//ui/file_manager/externs/background:drive_sync_handler.m", - "//ui/file_manager/externs/background:duplicate_finder.m", - "//ui/file_manager/externs/background:file_browser_background_full.m", - "//ui/file_manager/externs/background:file_operation_manager.m", - "//ui/file_manager/externs/background:import_history.m", - "//ui/file_manager/externs/background:media_import_handler.m", - "//ui/file_manager/externs/background:media_scanner.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", + "//ui/file_manager/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/file_manager/externs/background:file_browser_background_full.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", ] extra_deps = [ ":modulize" ] @@ -280,7 +280,7 @@ js_library("main_background.m") { ":background.m", ":metrics_start.m", ":test_util.m", - "//ui/file_manager/base/js:error_counter.m", + "//ui/file_manager/file_manager/common/js:error_counter.m", ] } @@ -293,7 +293,8 @@ js_library("background_base") { "//ui/webui/resources/js:assert", "//ui/webui/resources/js:load_time_data", ] - externs_list = [ "//ui/file_manager/externs/background/background_base.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/background_base.js" ] } js_library("background_base.m") { @@ -301,9 +302,9 @@ js_library("background_base.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/background_base.m.js" ] deps = [ ":volume_manager_factory.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:background_base.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:background_base.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -313,11 +314,12 @@ js_library("background_base.m") { js_library("crostini") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/common/js:metrics", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:volume_manager", ] - externs_list = [ "//ui/file_manager/externs/background/crostini.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/crostini.js" ] } js_library("crostini.m") { @@ -325,9 +327,9 @@ js_library("crostini.m") { "$root_gen_dir/ui/file_manager/file_manager/background/js/crostini.m.js", ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:crostini.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -338,7 +340,8 @@ js_library("crostini.m") { js_library("mock_crostini") { testonly = true deps = [ ":crostini" ] - externs_list = [ "//ui/file_manager/externs/background/crostini.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/crostini.js" ] visibility = [] visibility = [ "//ui/file_manager/file_manager/*" ] } @@ -348,7 +351,7 @@ js_library("mock_crostini.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/mock_crostini.m.js" ] deps = [ ":crostini.m", - "//ui/file_manager/externs/background:crostini.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", ] visibility += [ "//ui/file_manager/file_manager/foreground/js:file_tasks_unittest.m", @@ -362,11 +365,11 @@ js_unittest("crostini_unittest.m") { deps = [ ":mock_crostini.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:crostini.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", "//ui/webui/resources/js:load_time_data.m", ] } @@ -387,14 +390,14 @@ js_library("device_handler.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/device_handler.m.js" ] deps = [ ":volume_manager_factory.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -407,13 +410,13 @@ js_unittest("device_handler_unittest.m") { ":mock_progress_center.m", ":mock_volume_manager.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", "//ui/webui/resources/js:load_time_data.m", ] } @@ -422,8 +425,8 @@ js_library("mock_drive_sync_handler") { testonly = true deps = [ "//ui/webui/resources/js/cr:event_target" ] externs_list = [ - "//ui/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/externs/drive_dialog_controller.js", + "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js", + "//ui/file_manager/file_manager/externs/drive_dialog_controller.js", ] visibility = [] visibility = [ "//ui/file_manager/file_manager/*" ] @@ -432,8 +435,8 @@ js_library("mock_drive_sync_handler") { js_library("mock_drive_sync_handler.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/mock_drive_sync_handler.m.js" ] deps = [ - "//ui/file_manager/externs:drive_dialog_controller.m", - "//ui/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/file_manager/externs:drive_dialog_controller.m", + "//ui/file_manager/file_manager/externs/background:drive_sync_handler.m", "//ui/webui/resources/js/cr:event_target.m", ] visibility += [ @@ -451,8 +454,8 @@ js_library("drive_sync_handler") { "//ui/webui/resources/js/cr:event_target", ] externs_list = [ - "//ui/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/externs/drive_dialog_controller.js", + "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js", + "//ui/file_manager/file_manager/externs/drive_dialog_controller.js", ] } @@ -461,12 +464,12 @@ js_library("drive_sync_handler.m") { deps = [ ":file_operation_util.m", ":launcher.m", - "//ui/file_manager/externs:drive_dialog_controller.m", - "//ui/file_manager/externs/background:drive_sync_handler.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:drive_dialog_controller.m", + "//ui/file_manager/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -478,7 +481,7 @@ js_unittest("drive_sync_handler_unittest.m") { ":drive_sync_handler.m", ":mock_progress_center.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -492,7 +495,9 @@ js_library("duplicate_finder") { "//ui/file_manager/file_manager/common/js:lru_cache", "//ui/file_manager/file_manager/common/js:metrics", ] - externs_list = [ "//ui/file_manager/externs/background/duplicate_finder.js" ] + externs_list = [ + "//ui/file_manager/file_manager/externs/background/duplicate_finder.js", + ] } js_library("duplicate_finder.m") { @@ -500,13 +505,13 @@ js_library("duplicate_finder.m") { deps = [ ":import_history.m", ":volume_manager_factory.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:duplicate_finder.m", - "//ui/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:lru_cache.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", ] extra_deps = [ ":modulize" ] @@ -518,28 +523,28 @@ js_unittest("duplicate_finder_unittest.m") { ":mock_volume_manager.m", ":test_import_history.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs/background:duplicate_finder.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs/background:duplicate_finder.m", ] } js_library("entry_location_impl") { - deps = [ "//ui/file_manager/base/js:volume_manager_types" ] - externs_list = [ "//ui/file_manager/externs/entry_location.js" ] + deps = [ "//ui/file_manager/file_manager/common/js:volume_manager_types" ] + externs_list = [ "//ui/file_manager/file_manager/externs/entry_location.js" ] } js_library("entry_location_impl.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/entry_location_impl.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:volume_info.m", ] extra_deps = [ ":modulize" ] @@ -555,11 +560,11 @@ js_library("file_operation_handler") { js_library("file_operation_handler.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/file_operation_handler.m.js" ] deps = [ - "//ui/file_manager/externs/background:file_operation_manager.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:file_operation_common.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", ] extra_deps = [ ":modulize" ] @@ -584,14 +589,13 @@ js_library("mock_file_operation_manager") { ":file_operation_manager", "//ui/webui/resources/js/cr:event_target", ] - externs_list = - [ "//ui/file_manager/externs/background/file_operation_manager.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/background/file_operation_manager.js" ] } js_library("mock_file_operation_manager.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/mock_file_operation_manager.m.js" ] deps = [ - "//ui/file_manager/externs/background:file_operation_manager.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -605,11 +609,11 @@ js_library("file_operation_manager") { ":trash", ":volume_manager_factory", "//ui/file_manager/file_manager/common/js:file_operation_common", + "//ui/file_manager/file_manager/common/js:xfm", "//ui/webui/resources/js:cr", "//ui/webui/resources/js/cr:event_target", ] - externs_list = - [ "//ui/file_manager/externs/background/file_operation_manager.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/background/file_operation_manager.js" ] } js_library("file_operation_manager.m") { @@ -619,14 +623,15 @@ js_library("file_operation_manager.m") { ":metadata_proxy.m", ":trash.m", ":volume_manager_factory.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:file_operation_common.m", "//ui/file_manager/file_manager/common/js:trash.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:xfm.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", "//ui/webui/resources/js:assert.m", ] @@ -639,13 +644,13 @@ js_unittest("file_operation_manager_unittest.m") { ":file_operation_util.m", ":volume_manager_factory.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/common/js:file_operation_common.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", "//ui/webui/resources/js:load_time_data.m", ] } @@ -690,8 +695,8 @@ js_unittest("metadata_proxy_unittest.m") { deps = [ ":metadata_proxy.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -708,16 +713,17 @@ js_library("import_history") { "//ui/file_manager/file_manager/common/js:importer_common", "//ui/file_manager/file_manager/common/js:util", ] - externs_list = [ "//ui/file_manager/externs/background/import_history.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/import_history.js" ] } js_library("import_history.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/import_history.m.js" ] deps = [ ":metadata_proxy.m", - "//ui/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", "//ui/webui/resources/js:assert.m", ] @@ -728,13 +734,13 @@ js_unittest("import_history_unittest.m") { deps = [ ":import_history.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:test_importer_common.m", "//ui/file_manager/file_manager/common/js:unittest_util.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", ] } @@ -775,7 +781,8 @@ js_library("launcher_search.m") { "//ui/file_manager/file_manager/common/js:util.m", ] - externs_list = [ "//ui/file_manager/externs/launcher_search_provider.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/launcher_search_provider.js" ] extra_deps = [ ":modulize" ] } @@ -789,11 +796,12 @@ js_library("media_import_handler") { ":task_queue", "//ui/file_manager/file_manager/common/js:importer_common", "//ui/file_manager/file_manager/common/js:metrics", + "//ui/file_manager/file_manager/common/js:xfm", ] externs_list = [ - "//ui/file_manager/externs/background/duplicate_finder.js", - "//ui/file_manager/externs/background/task_queue.js", - "//ui/file_manager/externs/background/media_import_handler.js", + "//ui/file_manager/file_manager/externs/background/duplicate_finder.js", + "//ui/file_manager/file_manager/externs/background/task_queue.js", + "//ui/file_manager/file_manager/externs/background/media_import_handler.js", ] } @@ -802,18 +810,19 @@ js_library("media_import_handler.m") { deps = [ ":file_operation_util.m", ":task_queue.m", - "//ui/file_manager/externs/background:drive_sync_handler.m", - "//ui/file_manager/externs/background:duplicate_finder.m", - "//ui/file_manager/externs/background:import_history.m", - "//ui/file_manager/externs/background:media_import_handler.m", - "//ui/file_manager/externs/background:media_scanner.m", - "//ui/file_manager/externs/background:progress_center.m", - "//ui/file_manager/externs/background:task_queue.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:xfm.m", + "//ui/file_manager/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", + "//ui/file_manager/file_manager/externs/background:task_queue.m", "//ui/webui/resources/js:assert.m", ] @@ -830,16 +839,16 @@ js_unittest("media_import_handler_unittest.m") { ":mock_volume_manager.m", ":test_import_history.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs/background:duplicate_finder.m", - "//ui/file_manager/externs/background:import_history.m", - "//ui/file_manager/externs/background:media_import_handler.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:test_importer_common.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/externs/background:media_import_handler.m", ] } @@ -849,7 +858,8 @@ js_library("mock_media_scanner") { ":media_scanner", ":test_import_history", ] - externs_list = [ "//ui/file_manager/externs/background/media_scanner.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/media_scanner.js" ] visibility = [] visibility = [ "//ui/file_manager/file_manager/*" ] } @@ -859,8 +869,8 @@ js_library("mock_media_scanner.m") { deps = [ ":media_scanner.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/externs/background:media_scanner.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", ] visibility += [ "//ui/file_manager/file_manager/foreground/js:import_controller_unittest.m", @@ -874,7 +884,8 @@ js_library("media_scanner") { ":file_operation_util", "//ui/file_manager/file_manager/common/js:importer_common", ] - externs_list = [ "//ui/file_manager/externs/background/media_scanner.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/media_scanner.js" ] } js_library("media_scanner.m") { @@ -882,8 +893,8 @@ js_library("media_scanner.m") { deps = [ ":file_operation_util.m", ":metadata_proxy.m", - "//ui/file_manager/externs/background:media_scanner.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", "//ui/webui/resources/js:assert.m", ] visibility += [ @@ -900,10 +911,10 @@ js_unittest("media_scanner_unittest.m") { ":mock_media_scanner.m", ":test_import_history.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/externs/background:media_scanner.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:unittest_util.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", ] } @@ -927,14 +938,14 @@ js_library("mock_volume_manager.m") { ":volume_info_list_impl.m", ":volume_manager_factory.m", ":volume_manager_impl.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_info_list.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.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_info_list.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", ] @@ -954,8 +965,8 @@ js_library("mock_progress_center") { js_library("mock_progress_center.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/mock_progress_center.m.js" ] deps = [ - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", ] visibility += [ "//ui/file_manager/file_manager/foreground/js:file_tasks_unittest.m" ] @@ -971,19 +982,19 @@ js_library("progress_center") { "//ui/webui/resources/js/cr:event_target", ] externs_list = [ - "//ui/file_manager/externs/background/progress_center.js", - "//ui/file_manager/externs/progress_center_panel.js", + "//ui/file_manager/file_manager/externs/background/progress_center.js", + "//ui/file_manager/file_manager/externs/progress_center_panel.js", ] } js_library("progress_center.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/progress_center.m.js" ] deps = [ - "//ui/file_manager/externs:progress_center_panel.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:progress_center_panel.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", ] extra_deps = [ ":modulize" ] @@ -1005,44 +1016,44 @@ js_library("runtime_loaded_test_util") { ":file_operation_util", ":test_util_base", ":volume_manager_factory", - "//ui/file_manager/base/js:error_counter", + "//ui/file_manager/file_manager/common/js:error_counter", "//ui/file_manager/file_manager/common/js:importer_common", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:progress_center_common", ] externs_list = [ "$externs_path/webview_tag.js", - "//ui/file_manager/externs/foreground_window.js", - "//ui/file_manager/externs/background/progress_center.js", - "//ui/file_manager/externs/background/media_import_handler.js", - "//ui/file_manager/externs/background/task_queue.js", - "//ui/file_manager/externs/background/duplicate_finder.js", - "//ui/file_manager/externs/background/crostini.js", - "//ui/file_manager/externs/progress_center_panel.js", - "//ui/file_manager/externs/background/media_scanner.js", - "//ui/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/externs/drive_dialog_controller.js", - "//ui/file_manager/externs/background_window.js", - "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/background/import_history.js", - "//ui/file_manager/externs/background/background_base.js", - "//ui/file_manager/externs/background/file_browser_background_full.js", + "//ui/file_manager/file_manager/externs/foreground_window.js", + "//ui/file_manager/file_manager/externs/background/progress_center.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/crostini.js", + "//ui/file_manager/file_manager/externs/progress_center_panel.js", + "//ui/file_manager/file_manager/externs/background/media_scanner.js", + "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js", + "//ui/file_manager/file_manager/externs/drive_dialog_controller.js", + "//ui/file_manager/file_manager/externs/background_window.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/background_base.js", + "//ui/file_manager/file_manager/externs/background/file_browser_background_full.js", ] } js_library("volume_info_impl") { - deps = [ "//ui/file_manager/base/js:volume_manager_types" ] - externs_list = [ "//ui/file_manager/externs/volume_info.js" ] + deps = [ "//ui/file_manager/file_manager/common/js:volume_manager_types" ] + externs_list = [ "//ui/file_manager/file_manager/externs/volume_info.js" ] } js_library("volume_info_impl.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/volume_info_impl.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_info.m", "//ui/webui/resources/js:assert.m", ] visibility += [ @@ -1055,16 +1066,17 @@ js_library("volume_info_impl.m") { js_library("task_queue") { deps = [ "//ui/file_manager/file_manager/common/js:importer_common" ] - externs_list = [ "//ui/file_manager/externs/background/task_queue.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/task_queue.js" ] } js_unittest("task_queue_unittest.m") { deps = [ ":task_queue.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/externs/background:task_queue.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/externs/background:task_queue.m", ] } @@ -1074,8 +1086,8 @@ js_library("task_queue.m") { ] deps = [ - "//ui/file_manager/externs/background:task_queue.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/externs/background:task_queue.m", ] extra_deps = [ ":modulize" ] } @@ -1087,9 +1099,9 @@ js_library("test_util_base.m") { visibility += related_apps sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/test_util_base.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js:assert.m", ] extra_deps = [ ":modulize" ] @@ -1133,9 +1145,9 @@ js_library("test_import_history.m") { js_library("trash") { deps = [ ":file_operation_util", - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/common/js:trash", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:volume_manager", ] } @@ -1144,8 +1156,8 @@ js_library("trash.m") { [ "$root_gen_dir/ui/file_manager/file_manager/background/js/trash.m.js" ] deps = [ ":file_operation_util.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:trash.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -1158,9 +1170,9 @@ js_unittest("trash_unittest.m") { ":mock_volume_manager.m", ":trash.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", "//ui/file_manager/file_manager/common/js:trash.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -1174,14 +1186,15 @@ js_library("volume_info_list_impl") { "//ui/webui/resources/js/cr:ui", "//ui/webui/resources/js/cr/ui:array_data_model", ] - externs_list = [ "//ui/file_manager/externs/volume_info_list.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/volume_info_list.js" ] } js_library("volume_info_list_impl.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/volume_info_list_impl.m.js" ] deps = [ - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_info_list.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs:volume_info_list.m", "//ui/webui/resources/js/cr/ui:array_data_model.m", ] @@ -1196,9 +1209,9 @@ js_unittest("mount_metrics_unittest.m") { deps = [ ":mount_metrics.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", ] } @@ -1216,7 +1229,7 @@ js_library("volume_manager_impl") { ":volume_manager_util", "//ui/file_manager/file_manager/common/js:async_util", ] - externs_list = [ "//ui/file_manager/externs/volume_manager.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/volume_manager.js" ] } js_library("volume_manager_impl.m") { @@ -1225,11 +1238,11 @@ js_library("volume_manager_impl.m") { ":entry_location_impl.m", ":volume_info_list_impl.m", ":volume_manager_util.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr:event_target.m", @@ -1246,7 +1259,7 @@ js_library("volume_manager_factory.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/volume_manager_factory.m.js" ] deps = [ ":volume_manager_impl.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] extra_deps = [ ":modulize" ] @@ -1259,10 +1272,10 @@ js_unittest("volume_manager_unittest.m") { ":volume_manager_impl.m", ":volume_manager_util.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js:load_time_data.m", ] } @@ -1270,9 +1283,9 @@ js_unittest("volume_manager_unittest.m") { js_library("volume_manager_util") { deps = [ ":volume_info_impl", - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } @@ -1280,9 +1293,9 @@ js_library("volume_manager_util.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/volume_manager_util.m.js" ] deps = [ ":volume_info_impl.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", ] extra_deps = [ ":modulize" ] @@ -1365,6 +1378,13 @@ preprocess_folder = "$target_gen_dir/../../../preprocessed/file_manager/background/js", root_build_dir) +files_app_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/file_manager", + root_build_dir) +image_loader_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/image_loader", + root_build_dir) + optimize_webui("build") { host = "file_manager" @@ -1373,6 +1393,11 @@ optimize_webui("build") { js_out_files = [ "main_background.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":main_background.m", "//ui/file_manager:preprocess_generated", 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 3e42f821bbe..a5f6cd92b4f 100644 --- a/chromium/ui/file_manager/file_manager/common/js/BUILD.gn +++ b/chromium/ui/file_manager/file_manager/common/js/BUILD.gn @@ -8,7 +8,6 @@ import("//ui/file_manager/base/gn/js_test_gen_html.gni") import("//ui/webui/resources/js/cr.gni") import("//ui/webui/resources/tools/js_modulizer.gni") -# TODO(tapted): This entire folder should move to //ui/file_manager/base. visibility = [ "//chromeos/components/file_manager/resources/*", "//ui/file_manager/*", @@ -28,38 +27,49 @@ group("closure_compile") { js_type_check("closure_compile_module") { uses_legacy_modules = true deps = [ + ":app_util", ":async_util", + ":error_counter", ":file_operation_common", ":file_type", ":files_app_entry_types", + ":filtered_volume_manager", ":importer_common", ":lru_cache", ":metrics", ":metrics_base", ":mock_entry", + ":power", ":progress_center_common", ":storage_adapter", ":trash", ":util", - "//ui/file_manager/base/js:volume_manager_types", + ":volume_manager_types", + ":xfm", ] } js_type_check("closure_compile_jsmodules") { deps = [ + ":app_util.m", ":async_util.m", + ":error_counter.m", ":file_operation_common.m", ":file_type.m", ":files_app_entry_types.m", + ":filtered_volume_manager.m", ":importer_common.m", ":lru_cache.m", ":metrics.m", ":metrics_base.m", ":mock_entry.m", + ":power.m", ":progress_center_common.m", ":storage_adapter.m", ":trash.m", ":util.m", + ":volume_manager_types.m", + ":xfm.m", ] closure_flags = strict_error_checking_closure_args + [ @@ -73,6 +83,8 @@ js_type_check("test_support_type_check") { uses_legacy_modules = true testonly = true deps = [ + ":mock_chrome", + ":test_error_reporting", ":test_importer_common", ":unittest_util", ] @@ -81,6 +93,8 @@ js_type_check("test_support_type_check") { js_type_check("test_support_modules_type_check") { testonly = true deps = [ + ":mock_chrome.m", + ":test_error_reporting.m", ":test_importer_common.m", ":unittest_util.m", ] @@ -90,6 +104,32 @@ js_type_check("test_support_modules_type_check") { [ "browser_resolver_prefix_replacements=\"chrome://test/=./\"" ] } +js_library("app_util") { + deps = [ + ":volume_manager_types", + ":xfm", + "//ui/file_manager/file_manager/externs:volume_manager", + ] + externs_list = [ + "//ui/file_manager/file_manager/externs/app_window_common.js", + "//ui/file_manager/file_manager/externs/background/background_base.js", + ] +} + +js_library("app_util.m") { + sources = + [ "$root_gen_dir/ui/file_manager/file_manager/common/js/app_util.m.js" ] + deps = [ + "//ui/file_manager/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:background_base.m", + ] + externs_list = + [ "//ui/file_manager/file_manager/externs/app_window_common.js" ] + + extra_deps = [ ":modulize" ] +} + js_library("async_util") { } @@ -100,11 +140,22 @@ js_library("async_util.m") { extra_deps = [ ":modulize" ] } +js_library("error_counter") { +} + +js_library("error_counter.m") { + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/common/js/error_counter.m.js", + ] + + extra_deps = [ ":modulize" ] +} + js_library("files_app_entry_types") { - deps = [ "//ui/file_manager/externs:file_manager_private" ] + deps = [ "//ui/file_manager/file_manager/externs:file_manager_private" ] externs_list = [ - "//ui/file_manager/externs/files_app_entry_interfaces.js", - "//ui/file_manager/externs/volume_info.js", + "//ui/file_manager/file_manager/externs/files_app_entry_interfaces.js", + "//ui/file_manager/file_manager/externs/volume_info.js", ] } @@ -113,8 +164,8 @@ js_unittest("files_app_entry_types_unittest.m") { ":files_app_entry_types.m", ":mock_entry.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/externs:volume_info.m", "//ui/webui/resources/js:assert.m", ] } @@ -122,8 +173,8 @@ js_unittest("files_app_entry_types_unittest.m") { js_library("files_app_entry_types.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/files_app_entry_types.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", ] extra_deps = [ ":modulize" ] @@ -132,7 +183,7 @@ js_library("files_app_entry_types.m") { js_library("file_type") { deps = [ ":files_app_entry_types", - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } @@ -141,8 +192,8 @@ js_library("file_type.m") { [ "$root_gen_dir/ui/file_manager/file_manager/common/js/file_type.m.js" ] deps = [ ":files_app_entry_types.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", "//ui/webui/resources/js:assert.m", ] @@ -154,20 +205,53 @@ js_unittest("file_type_unittest.m") { ":file_type.m", ":mock_entry.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", ] } js_library("file_operation_common") { deps = [ ":util" ] - externs_list = [ "//ui/file_manager/externs/files_app_entry_interfaces.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/files_app_entry_interfaces.js" ] } js_library("file_operation_common.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/file_operation_common.m.js" ] deps = [ ":util.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("filtered_volume_manager") { + deps = [ + "//ui/file_manager/file_manager/common/js:async_util", + "//ui/file_manager/file_manager/common/js:files_app_entry_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:volume_manager", + "//ui/webui/resources/js:cr", + "//ui/webui/resources/js/cr/ui:array_data_model", + ] + externs_list = [ "//ui/file_manager/file_manager/externs/background/volume_manager_factory.js" ] +} + +js_library("filtered_volume_manager.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/filtered_volume_manager.m.js" ] + deps = [ + "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.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_info_list.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js/cr:event_target.m", + "//ui/webui/resources/js/cr/ui:array_data_model.m", ] extra_deps = [ ":modulize" ] @@ -181,8 +265,9 @@ js_library("importer_common") { visibility = [ "//ui/file_manager/file_manager/*" ] deps = [ ":file_type", - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", + ":xfm", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:volume_manager", ] } @@ -192,10 +277,10 @@ js_library("importer_common.m") { ] deps = [ ":file_type.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.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", ] extra_deps = [ ":modulize" ] @@ -206,8 +291,8 @@ js_library("test_importer_common") { deps = [ ":importer_common", ":unittest_util", - "//ui/file_manager/base/js:mock_chrome", - "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/file_manager/common/js:mock_chrome", + "//ui/file_manager/file_manager/common/js:test_error_reporting", ] visibility = [] visibility = [ "//ui/file_manager/file_manager/*" ] @@ -229,11 +314,11 @@ js_unittest("importer_common_unittest.m") { ":mock_entry.m", ":test_importer_common.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", ] } @@ -254,12 +339,21 @@ js_unittest("lru_cache_unittest.m") { ] } +js_library("mediasession_types") { +} + +js_library("mediasession_types.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/mediasession_types.m.js" ] + + extra_deps = [ ":modulize" ] +} + js_library("metrics") { visibility = [] visibility = [ "//ui/file_manager/file_manager/*" ] deps = [ ":metrics_base", - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:file_manager_private", "//ui/webui/resources/js:assert", ] } @@ -287,6 +381,19 @@ js_library("metrics_base.m") { extra_deps = [ ":modulize" ] } +js_library("mock_chrome") { + testonly = true +} + +js_library("mock_chrome.m") { + testonly = true + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/common/js/mock_chrome.m.js", + ] + + extra_deps = [ ":modulize" ] +} + js_library("mock_entry") { deps = [ ":util", @@ -311,6 +418,16 @@ js_library("progress_center_common.m") { extra_deps = [ ":modulize" ] } +js_library("power") { +} + +js_library("power.m") { + sources = + [ "$root_gen_dir/ui/file_manager/file_manager/common/js/power.m.js" ] + + extra_deps = [ ":modulize" ] +} + js_library("storage_adapter") { } @@ -322,15 +439,48 @@ js_library("storage_adapter.m") { extra_deps = [ ":modulize" ] } +js_library("test_error_reporting") { + testonly = true + deps = [ + # Note we allow targets depending on test_error_reporting to access + # webui_resource_test transitively. + "//ui/webui/resources/js:webui_resource_test", + ] +} + +js_library("test_error_reporting.m") { + testonly = true + sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/test_error_reporting.m.js" ] + + extra_deps = [ ":modulize" ] +} + +js_library("xfm") { + deps = [ + ":power", + ":storage_adapter", + ] +} + +js_library("xfm.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/xfm.m.js" ] + deps = [ + ":power.m", + ":storage_adapter.m", + ] + + extra_deps = [ ":modulize" ] +} + js_library("trash") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:files_app_entry_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] externs_list = [ - "//ui/file_manager/externs/files_app_entry_interfaces.js", - "//ui/file_manager/externs/volume_info.js", - "//ui/file_manager/externs/volume_manager.js", + "//ui/file_manager/file_manager/externs/files_app_entry_interfaces.js", + "//ui/file_manager/file_manager/externs/volume_info.js", + "//ui/file_manager/file_manager/externs/volume_manager.js", ] } @@ -340,9 +490,9 @@ js_library("trash.m") { deps = [ ":files_app_entry_types.m", ":util.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", ] @@ -371,12 +521,12 @@ js_library("unittest_util.m") { js_library("util") { deps = [ ":files_app_entry_types", - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:file_manager_private", # TODO(tapted): Remove these base util dependencies, which exist temporarily # to allow targets to depend only on util, if they depend on one of these. - "//ui/file_manager/base/js:app_util", - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:app_util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/webui/resources/js:load_time_data", "//ui/webui/resources/js:util", "//ui/webui/resources/js/cr:event_target", @@ -384,11 +534,11 @@ js_library("util") { ] externs_list = [ "$externs_path/command_line_private.js", - "//ui/file_manager/externs/entry_location.js", - "//ui/file_manager/externs/platform.js", - "//ui/file_manager/externs/volume_info.js", - "//ui/file_manager/externs/volume_info_list.js", - "//ui/file_manager/externs/volume_manager.js", + "//ui/file_manager/file_manager/externs/entry_location.js", + "//ui/file_manager/file_manager/externs/platform.js", + "//ui/file_manager/file_manager/externs/volume_info.js", + "//ui/file_manager/file_manager/externs/volume_info_list.js", + "//ui/file_manager/file_manager/externs/volume_manager.js", ] } @@ -397,13 +547,13 @@ js_library("util.m") { deps = [ ":files_app_entry_types.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:file_manager_private", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:file_manager_private", + "//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/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js:util.m", @@ -411,8 +561,8 @@ js_library("util.m") { ] externs_list = [ - "//ui/file_manager/externs/platform.js", - "//ui/file_manager/externs/app_window_common.js", + "//ui/file_manager/file_manager/externs/platform.js", + "//ui/file_manager/file_manager/externs/app_window_common.js", ] extra_deps = [ ":modulize" ] @@ -424,11 +574,33 @@ js_unittest("util_unittest.m") { ":mock_entry.m", ":util.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", ] } +js_library("volume_manager_types") { + deps = [ + "//ui/file_manager/file_manager/externs:file_manager_private", + "//ui/webui/resources/js:assert", + ] +} + +js_unittest("volume_manager_types_unittest.m") { + deps = [ ":volume_manager_types.m" ] +} + +js_library("volume_manager_types.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/common/js/volume_manager_types.m.js" ] + + deps = [ + "//ui/file_manager/file_manager/externs:file_manager_private", + "//ui/webui/resources/js:assert.m", + ] + + extra_deps = [ ":modulize" ] +} + js_test_gen_html("js_test_gen_html_modules") { js_module = true deps = [ @@ -437,6 +609,7 @@ js_test_gen_html("js_test_gen_html_modules") { ":importer_common_unittest.m", ":lru_cache_unittest.m", ":util_unittest.m", + ":volume_manager_types_unittest.m", ] closure_flags = @@ -450,21 +623,30 @@ js_test_gen_html("js_test_gen_html_modules") { js_modulizer("modulize") { input_files = [ + "app_util.js", "async_util.js", + "error_counter.js", "file_operation_common.js", "file_type.js", "files_app_entry_types.js", + "filtered_volume_manager.js", "importer_common.js", "lru_cache.js", + "mediasession_types.js", "metrics.js", "metrics_base.js", + "mock_chrome.js", "mock_entry.js", + "power.js", "progress_center_common.js", "storage_adapter.js", + "test_error_reporting.js", "test_importer_common.js", "trash.js", "unittest_util.js", "util.js", + "volume_manager_types.js", + "xfm.js", ] namespace_rewrites = cr_namespace_rewrites diff --git a/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn b/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn index d2a1b7ddc2d..53c334d5939 100644 --- a/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn +++ b/chromium/ui/file_manager/file_manager/cws_widget/BUILD.gn @@ -25,6 +25,7 @@ js_type_check("closure_compile_jsmodules") { } js_type_check("closure_compile_module") { + uses_legacy_modules = true deps = [ ":app_installer", ":cws_webview_client", diff --git a/chromium/ui/file_manager/file_manager/externs/BUILD.gn b/chromium/ui/file_manager/file_manager/externs/BUILD.gn new file mode 100644 index 00000000000..010dd7268f9 --- /dev/null +++ b/chromium/ui/file_manager/file_manager/externs/BUILD.gn @@ -0,0 +1,193 @@ +# 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/tools/js_modulizer.gni") + +js_library("file_manager_private") { + sources = [] + + # The file_manager_private extern depends on file_system_provider and + # extension APIs. Ensure they're pulled in together. + externs_list = [ + "$externs_path/chrome.js", + "$externs_path/chrome_extensions.js", + "$externs_path/file_manager_private.js", + "$externs_path/file_system_provider.js", + ] +} + +js_library("background_window.m") { + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/externs/background_window.m.js", + ] + + deps = + [ "//ui/file_manager/file_manager/externs/background:background_base.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("command_handler_deps.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/command_handler_deps.m.js" ] + deps = [ + ":files_app_entry_interfaces.m", + ":volume_manager.m", + "background:crostini.m", + "background:file_operation_manager.m", + "background:progress_center.m", + "//ui/file_manager/file_manager/foreground/js:actions_controller.m", + "//ui/file_manager/file_manager/foreground/js:dialog_type.m", + "//ui/file_manager/file_manager/foreground/js:directory_contents.m", + "//ui/file_manager/file_manager/foreground/js:directory_model.m", + "//ui/file_manager/file_manager/foreground/js:directory_tree_naming_controller.m", + "//ui/file_manager/file_manager/foreground/js:file_selection.m", + "//ui/file_manager/file_manager/foreground/js:file_transfer_controller.m", + "//ui/file_manager/file_manager/foreground/js:naming_controller.m", + "//ui/file_manager/file_manager/foreground/js:providers_model.m", + "//ui/file_manager/file_manager/foreground/js:spinner_controller.m", + "//ui/file_manager/file_manager/foreground/js:task_controller.m", + "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", + "//ui/file_manager/file_manager/foreground/js/ui:directory_tree.m", + "//ui/file_manager/file_manager/foreground/js/ui:file_manager_ui.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("directory_change_event.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/directory_change_event.m.js" ] + deps = [ ":files_app_entry_interfaces.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("drive_dialog_controller.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/drive_dialog_controller.m.js" ] + + extra_deps = [ ":modulize" ] +} + +js_library("entries_changed_event.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/entries_changed_event.m.js" ] + + deps = [ "//ui/file_manager/file_manager/common/js:util.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("entry_location.m") { + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/externs/entry_location.m.js", + ] + + deps = [ + ":volume_info.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("exif_entry.m") { + sources = + [ "$root_gen_dir/ui/file_manager/file_manager/externs/exif_entry.m.js" ] + + deps = [ + "//ui/file_manager/file_manager/foreground/js/metadata:exif_constants.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("files_app_entry_interfaces.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/files_app_entry_interfaces.m.js" ] + + deps = [ "//ui/file_manager/file_manager/common/js:volume_manager_types.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("metadata_worker_window.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/metadata_worker_window.m.js" ] + + extra_deps = [ ":modulize" ] +} + +js_library("progress_center_panel.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/progress_center_panel.m.js" ] + + deps = [ "//ui/file_manager/file_manager/common/js:progress_center_common.m" ] + extra_deps = [ ":modulize" ] +} + +js_library("volume_manager") { + sources = [] + + # Encapsulate volume_manager.js and its dependencies. Note this should really + # depend on volume_manager_types.js as well, but that's not an extern. + externs_list = [ + "entry_location.js", + "files_app_entry_interfaces.js", + "volume_info.js", + "volume_info_list.js", + "volume_manager.js", + ] +} + +js_library("volume_manager.m") { + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/externs/volume_manager.m.js", + ] + + deps = [ + ":entry_location.m", + ":files_app_entry_interfaces.m", + ":volume_info.m", + ":volume_info_list.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("volume_info.m") { + sources = + [ "$root_gen_dir/ui/file_manager/file_manager/externs/volume_info.m.js" ] + + deps = [ + ":files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("volume_info_list.m") { + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/externs/volume_info_list.m.js", + ] + + deps = [ ":volume_info.m" ] + + extra_deps = [ ":modulize" ] +} + +js_modulizer("modulize") { + input_files = [ + "background_window.js", + "command_handler_deps.js", + "directory_change_event.js", + "drive_dialog_controller.js", + "entries_changed_event.js", + "entry_location.js", + "exif_entry.js", + "files_app_entry_interfaces.js", + "metadata_worker_window.js", + "progress_center_panel.js", + "volume_info.js", + "volume_info_list.js", + "volume_manager.js", + ] +} diff --git a/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn b/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn new file mode 100644 index 00000000000..48f665011c6 --- /dev/null +++ b/chromium/ui/file_manager/file_manager/externs/background/BUILD.gn @@ -0,0 +1,147 @@ +# 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("//third_party/closure_compiler/compile_js.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") + +js_library("file_browser_background_full") { + sources = [] + + externs_list = [ + "background_base.js", + "crostini.js", + "../drive_dialog_controller.js", + "drive_sync_handler.js", + "duplicate_finder.js", + "file_browser_background_full.js", + "file_operation_manager.js", + "import_history.js", + "media_import_handler.js", + "media_scanner.js", + "progress_center.js", + "../progress_center_panel.js", + "task_queue.js", + ] +} + +js_library("file_browser_background_full.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/file_browser_background_full.m.js" ] + deps = [ + ":background_base.m", + ":crostini.m", + ":drive_sync_handler.m", + ":file_operation_manager.m", + ":import_history.m", + ":media_import_handler.m", + ":media_scanner.m", + ":progress_center.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("background_base.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/background_base.m.js" ] + + deps = [ "..:volume_manager.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("drive_sync_handler.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/drive_sync_handler.m.js" ] + + deps = [ "..:drive_dialog_controller.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("duplicate_finder.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/duplicate_finder.m.js" ] + deps = [ + ":import_history.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("crostini.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/crostini.m.js" ] + deps = [ "..:volume_manager.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("file_operation_manager.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/file_operation_manager.m.js" ] + deps = [ + "..:files_app_entry_interfaces.m", + "..:volume_manager.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("import_history.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/import_history.m.js" ] + deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("media_import_handler.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/media_import_handler.m.js" ] + deps = [ + ":drive_sync_handler.m", + ":duplicate_finder.m", + ":import_history.m", + ":media_scanner.m", + ":progress_center.m", + ":task_queue.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("media_scanner.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/media_scanner.m.js" ] + deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] + + extra_deps = [ ":modulize" ] +} + +js_library("progress_center.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/progress_center.m.js" ] + deps = [ + "..:progress_center_panel.m", + "//ui/file_manager/file_manager/common/js:progress_center_common.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("task_queue.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/externs/background/task_queue.m.js" ] + deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] + + extra_deps = [ ":modulize" ] +} + +js_modulizer("modulize") { + input_files = [ + "file_browser_background_full.js", + "background_base.js", + "crostini.js", + "drive_sync_handler.js", + "duplicate_finder.js", + "file_operation_manager.js", + "import_history.js", + "media_import_handler.js", + "media_scanner.js", + "progress_center.js", + "task_queue.js", + ] +} 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 acd4f7f4c10..ba36c51a64d 100644 --- a/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn +++ b/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn @@ -104,8 +104,8 @@ polymer_modulizer("files_format_dialog") { 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/base/js/volume_manager_types.html|VolumeManagerCommon", - "ui/file_manager/externs/volume_info.html|VolumeInfo", + "ui/file_manager/file_manager/common/js/volume_manager_types.html|VolumeManagerCommon", + "ui/file_manager/file_manager/externs/volume_info.html|VolumeInfo", ] } @@ -115,10 +115,10 @@ js_library("files_format_dialog.m") { deps = [ "//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", "//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", "//ui/webui/resources/cr_elements/cr_input:cr_input.m", @@ -241,7 +241,7 @@ js_unittest("files_password_dialog_unittest.m") { deps = [ ":files_password_dialog.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/webui/resources/js:assert.m", ] } @@ -404,7 +404,7 @@ js_unittest("files_tooltip_unittest.m") { deps = [ ":files_tooltip.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } 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 58c917fde2b..de71fe932a9 100644 --- a/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn @@ -10,7 +10,7 @@ import("//ui/webui/resources/js/cr.gni") import("//ui/webui/resources/tools/js_modulizer.gni") visibility = [ - "//ui/file_manager/externs/*", + "//ui/file_manager/file_manager/externs/*", "//ui/file_manager/file_manager/foreground/*", "//ui/file_manager/file_manager/test/*", ] @@ -28,6 +28,12 @@ group("closure_compile") { js_type_check("closure_compile_jsmodules") { is_polymer3 = true + closure_flags = default_closure_args + [ + "js_module_root=gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + ] + deps = [ ":actions_controller.m", ":actions_model.m", @@ -161,29 +167,29 @@ js_library("closure_compile_externs") { externs_list = [ "$externs_path/command_line_private.js", "$externs_path/metrics_private.js", - "//ui/file_manager/externs/background/crostini.js", - "//ui/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/externs/background/background_base.js", - "//ui/file_manager/externs/background/file_browser_background_full.js", - "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/background/media_import_handler.js", - "//ui/file_manager/externs/background/task_queue.js", - "//ui/file_manager/externs/background/duplicate_finder.js", - "//ui/file_manager/externs/background/media_scanner.js", - "//ui/file_manager/externs/background/progress_center.js", - "//ui/file_manager/externs/background_window.js", - "//ui/file_manager/externs/chrome_echo_private.js", - "//ui/file_manager/externs/chrome_webstore_widget_private.js", - "//ui/file_manager/externs/command_handler_deps.js", - "//ui/file_manager/externs/css_rule.js", - "//ui/file_manager/externs/directory_change_event.js", - "//ui/file_manager/externs/drive_dialog_controller.js", - "//ui/file_manager/externs/entries_changed_event.js", - "//ui/file_manager/externs/gallery_foreground.js", - "//ui/file_manager/externs/menu_item_update_event.js", - "//ui/file_manager/externs/paper_elements.js", - "//ui/file_manager/externs/platform.js", - "//ui/file_manager/externs/search_item.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", ] } @@ -221,8 +227,8 @@ js_library("actions_controller.m") { ":folder_shortcuts_data_model.m", "metadata:metadata_model.m", "ui:file_manager_ui.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:drive_sync_handler.m", "//ui/webui/resources/js/cr/ui:context_menu_handler.m", ] @@ -239,8 +245,9 @@ js_library("actions_model") { "//ui/file_manager/file_manager/foreground/js/ui:action_model_ui", "//ui/webui/resources/js:cr", ] - externs_list = - [ "//ui/file_manager/externs/background/drive_sync_handler.js" ] + externs_list = [ + "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js", + ] } js_library("actions_model.m") { @@ -249,11 +256,11 @@ js_library("actions_model.m") { ":folder_shortcuts_data_model.m", "metadata:metadata_model.m", "ui:action_model_ui.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:drive_sync_handler.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:drive_sync_handler.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr:event_target.m", @@ -307,13 +314,14 @@ js_unittest("actions_model_unittest.m") { "ui:files_alert_dialog.m", "ui:list_container.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/background/js:mock_drive_sync_handler.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/common/js:xfm.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -349,7 +357,7 @@ js_library("mock_directory_model.m") { deps = [ ":directory_contents.m", ":directory_model.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -385,7 +393,7 @@ js_library("mock_navigation_list_model.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/mock_navigation_list_model.m.js" ] deps = [ ":navigation_list_model.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -431,7 +439,7 @@ js_library("app_state_controller.m") { ":directory_model.m", "ui:file_manager_ui.m", "ui:list_container.m", - "//ui/file_manager/base/js:app_util.m", + "//ui/file_manager/file_manager/common/js:app_util.m", "//ui/file_manager/file_manager/common/js:util.m", "//ui/webui/resources/js:assert.m", ] @@ -443,7 +451,7 @@ js_library("column_visibility_controller") { deps = [ ":directory_model", "ui:file_manager_ui", - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } @@ -452,9 +460,9 @@ js_library("column_visibility_controller.m") { deps = [ ":directory_model.m", "ui:file_manager_ui.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] extra_deps = [ ":modulize" ] @@ -501,10 +509,10 @@ js_library("crostini_controller.m") { ":file_manager_commands.m", ":navigation_list_model.m", "ui:directory_tree.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs/background:crostini.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", "//ui/file_manager/file_manager/foreground/elements:files_message.m", "//ui/file_manager/file_manager/foreground/elements:files_toast.m", "//ui/webui/resources/js:assert.m", @@ -539,10 +547,10 @@ js_library("dialog_action_controller.m") { ":naming_controller.m", "metadata:metadata_model.m", "ui:dialog_footer.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -567,11 +575,11 @@ js_library("directory_contents") { ":constants", ":file_list_model", "metadata:metadata_model", - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/common/js:async_util", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:volume_manager", "//ui/webui/resources/js:cr", "//ui/webui/resources/js/cr/ui:array_data_model", ] @@ -583,12 +591,12 @@ js_library("directory_contents.m") { ":constants.m", ":file_list_model.m", "metadata:metadata_model.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr:event_target.m", @@ -601,9 +609,9 @@ js_unittest("directory_contents_unittest.m") { deps = [ ":directory_contents.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] } @@ -615,8 +623,8 @@ js_library("directory_model") { "//ui/file_manager/file_manager/common/js:importer_common", ] externs_list = [ - "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/entries_changed_event.js", + "//ui/file_manager/file_manager/externs/background/file_operation_manager.js", + "//ui/file_manager/file_manager/externs/entries_changed_event.js", ] } @@ -629,15 +637,15 @@ js_library("directory_model.m") { ":file_watcher.m", "metadata:metadata_model.m", "ui:file_list_selection_model.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entries_changed_event.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entries_changed_event.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/externs/background:file_operation_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr:event_target.m", @@ -658,9 +666,9 @@ js_library("navigation_uma") { js_library("navigation_uma.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/navigation_uma.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] extra_deps = [ ":modulize" ] @@ -680,8 +688,8 @@ js_library("directory_tree_naming_controller.m") { deps = [ ":directory_model.m", "ui:directory_tree.m", - "//ui/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:volume_info.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr/ui:dialogs.m", ] @@ -694,7 +702,8 @@ js_library("drive_dialog_controller") { "ui:file_manager_ui", "ui:files_confirm_dialog", ] - externs_list = [ "//ui/file_manager/externs/drive_dialog_controller.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/drive_dialog_controller.js" ] } js_library("drive_dialog_controller.m") { @@ -702,7 +711,7 @@ js_library("drive_dialog_controller.m") { deps = [ "ui:file_manager_ui.m", "ui:files_confirm_dialog.m", - "//ui/file_manager/externs:drive_dialog_controller.m", + "//ui/file_manager/file_manager/externs:drive_dialog_controller.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -780,10 +789,10 @@ js_library("file_list_model.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/file_list_model.m.js" ] deps = [ "metadata:metadata_model.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js/cr/ui:array_data_model.m", ] @@ -836,7 +845,7 @@ js_library("file_manager") { "ui:commandbutton", "ui:directory_tree", "ui:file_manager_ui", - "//ui/file_manager/base/js:filtered_volume_manager", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager", "//ui/file_manager/file_manager/common/js:storage_adapter", "//ui/webui/resources/js/cr/ui:list_selection_model", ] @@ -898,23 +907,23 @@ js_library("file_manager.m") { "ui:file_manager_ui.m", "ui:file_metadata_formatter.m", "ui:file_table.m", - "//ui/file_manager/base/js:filtered_volume_manager.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:background_window.m", - "//ui/file_manager/externs:command_handler_deps.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs/background:crostini.m", - "//ui/file_manager/externs/background:file_browser_background_full.m", - "//ui/file_manager/externs/background:file_operation_manager.m", - "//ui/file_manager/externs/background:import_history.m", - "//ui/file_manager/externs/background:media_import_handler.m", - "//ui/file_manager/externs/background:media_scanner.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:storage_adapter.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:background_window.m", + "//ui/file_manager/file_manager/externs:command_handler_deps.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", + "//ui/file_manager/file_manager/externs/background:file_browser_background_full.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/foreground/elements:files_message.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", @@ -952,9 +961,9 @@ js_library("file_manager_commands") { "//ui/webui/resources/cr_elements/cr_input:cr_input", ] externs_list = [ - "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/background/progress_center.js", - "//ui/file_manager/externs/command_handler_deps.js", + "//ui/file_manager/file_manager/externs/background/file_operation_manager.js", + "//ui/file_manager/file_manager/externs/background/progress_center.js", + "//ui/file_manager/file_manager/externs/command_handler_deps.js", ] } @@ -972,11 +981,6 @@ js_library("file_manager_commands.m") { ":webui_command_extender.m", "ui:directory_tree.m", "ui:files_confirm_dialog.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:command_handler_deps.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:file_operation_common.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", @@ -984,6 +988,11 @@ js_library("file_manager_commands.m") { "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:trash.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:command_handler_deps.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/webui/resources/js:assert.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -999,10 +1008,10 @@ js_unittest("file_manager_commands_unittest.m") { ":file_manager_commands.m", ":file_tasks.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js:load_time_data.m", ] } @@ -1013,9 +1022,9 @@ js_library("file_selection") { ":directory_model", "metadata:metadata_model", "ui:list_container", - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:file_type", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", ] @@ -1028,11 +1037,11 @@ js_library("file_selection.m") { ":directory_model.m", "metadata:metadata_model.m", "ui:list_container.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr:event_target.m", @@ -1052,8 +1061,8 @@ js_library("file_tasks") { "//ui/file_manager/file_manager/common/js:async_util", ] externs_list = [ - "//ui/file_manager/externs/background/crostini.js", - "//ui/file_manager/externs/background/progress_center.js", + "//ui/file_manager/file_manager/externs/background/crostini.js", + "//ui/file_manager/file_manager/externs/background/progress_center.js", ] } @@ -1075,16 +1084,16 @@ js_library("file_tasks.m") { "ui:files_confirm_dialog.m", "ui:files_menu.m", "ui:multi_menu_button.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:crostini.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/foreground/elements:files_password_dialog.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", @@ -1105,16 +1114,16 @@ js_unittest("file_tasks_unittest.m") { "metadata:metadata_model.m", "ui:file_manager_ui.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/background/js:mock_crostini.m", "//ui/file_manager/file_manager/background/js:mock_progress_center.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/foreground/elements:files_password_dialog.m", ] } @@ -1134,7 +1143,8 @@ js_library("file_transfer_controller") { "//ui/file_manager/file_manager/common/js:progress_center_common", "//ui/file_manager/file_manager/common/js:storage_adapter", ] - externs_list = [ "//ui/file_manager/externs/background/progress_center.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/progress_center.js" ] } js_library("file_transfer_controller.m") { @@ -1149,16 +1159,16 @@ js_library("file_transfer_controller.m") { "ui:directory_tree.m", "ui:drag_selector.m", "ui:list_container.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:file_operation_manager.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.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/externs/background:file_operation_manager.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -1185,14 +1195,14 @@ js_unittest("file_transfer_controller_unittest.m") { "ui:file_table.m", "ui:list_container.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:file_operation_manager.m", - "//ui/file_manager/externs/background:import_history.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr:ui.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -1211,8 +1221,8 @@ js_library("file_type_filters_controller.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/file_type_filters_controller.m.js" ] deps = [ ":directory_model.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", ] extra_deps = [ ":modulize" ] @@ -1223,10 +1233,10 @@ js_unittest("file_type_filters_controller_unittest.m") { ":directory_model.m", ":file_type_filters_controller.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:mock_chrome", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -1234,9 +1244,9 @@ js_unittest("file_type_filters_controller_unittest.m") { js_library("file_watcher") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:async_util", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/webui/resources/js:assert", ] } @@ -1244,9 +1254,9 @@ js_library("file_watcher") { js_library("file_watcher.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/file_watcher.m.js" ] deps = [ - "//ui/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -1256,11 +1266,11 @@ js_library("file_watcher.m") { js_library("folder_shortcuts_data_model") { deps = [ - "//ui/file_manager/base/js:filtered_volume_manager", - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:async_util", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/webui/resources/js/cr:event_target", ] } @@ -1268,11 +1278,11 @@ js_library("folder_shortcuts_data_model") { js_library("folder_shortcuts_data_model.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/folder_shortcuts_data_model.m.js" ] deps = [ - "//ui/file_manager/base/js:filtered_volume_manager.m", - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/common/js:async_util.m", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -1297,9 +1307,9 @@ js_library("gear_menu_controller.m") { "ui:gear_menu.m", "ui:multi_menu_button.m", "ui:providers_menu.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:directory_change_event.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:directory_change_event.m", ] extra_deps = [ ":modulize" ] @@ -1307,7 +1317,7 @@ js_library("gear_menu_controller.m") { js_library("holding_space_util") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:load_time_data", ] @@ -1316,8 +1326,8 @@ js_library("holding_space_util") { js_library("holding_space_util.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/holding_space_util.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -1340,10 +1350,10 @@ js_library("import_controller") { "//ui/file_manager/file_manager/common/js:importer_common", ] externs_list = [ - "//ui/file_manager/externs/background/media_import_handler.js", - "//ui/file_manager/externs/background/duplicate_finder.js", - "//ui/file_manager/externs/background/task_queue.js", - "//ui/file_manager/externs/command_handler_deps.js", + "//ui/file_manager/file_manager/externs/background/media_import_handler.js", + "//ui/file_manager/file_manager/externs/background/duplicate_finder.js", + "//ui/file_manager/file_manager/externs/background/task_queue.js", + "//ui/file_manager/file_manager/externs/command_handler_deps.js", ] } @@ -1351,16 +1361,16 @@ js_library("import_controller.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/import_controller.m.js" ] deps = [ ":file_selection.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:command_handler_deps.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:media_import_handler.m", - "//ui/file_manager/externs/background:media_scanner.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:command_handler_deps.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/externs/background:media_import_handler.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js:util.m", @@ -1373,16 +1383,16 @@ js_unittest("import_controller_unittest.m") { deps = [ ":import_controller.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:media_import_handler.m", - "//ui/file_manager/externs/background:media_scanner.m", "//ui/file_manager/file_manager/background/js:mock_media_scanner.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_info.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/file_manager/externs/background:media_scanner.m", "//ui/webui/resources/js:assert.m", ] } @@ -1408,7 +1418,7 @@ js_library("last_modified_controller.m") { js_library("launch_param") { deps = [ ":dialog_type", - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } @@ -1416,7 +1426,7 @@ js_library("launch_param.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/launch_param.m.js" ] deps = [ ":dialog_type.m", - "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", ] extra_deps = [ ":modulize" ] @@ -1428,7 +1438,7 @@ js_library("list_thumbnail_loader") { ":file_list_model", ":thumbnail_loader", "metadata:thumbnail_model", - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } @@ -1439,9 +1449,9 @@ js_library("list_thumbnail_loader.m") { ":file_list_model.m", ":thumbnail_loader.m", "metadata:thumbnail_model.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:lru_cache.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -1458,10 +1468,10 @@ js_unittest("list_thumbnail_loader_unittest.m") { "metadata:metadata_model.m", "metadata:thumbnail_model.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -1511,11 +1521,11 @@ js_library("main_window_component.m") { "ui:file_manager_ui.m", "ui:file_tap_handler.m", "ui:list_container.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:directory_change_event.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:directory_change_event.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] extra_deps = [ ":modulize" ] @@ -1540,9 +1550,9 @@ js_library("metadata_box_controller.m") { "metadata:metadata_item.m", "metadata:metadata_model.m", "ui:file_metadata_formatter.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/foreground/elements:files_metadata_box.m", "//ui/file_manager/file_manager/foreground/elements:files_quick_view.m", "//ui/webui/resources/js:assert.m", @@ -1626,13 +1636,13 @@ js_library("navigation_list_model.m") { ":directory_model.m", ":folder_shortcuts_data_model.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", "//ui/file_manager/file_manager/common/js:trash.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.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/webui/resources/js:load_time_data.m", "//ui/webui/resources/js/cr:event_target.m", ] @@ -1649,28 +1659,28 @@ js_unittest("navigation_list_model_unittest.m") { ":mock_folder_shortcut_data_model.m", ":navigation_list_model.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", "//ui/file_manager/file_manager/background/js:volume_info_impl.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", ] } js_library("path_component") { - deps = [ "//ui/file_manager/base/js:volume_manager_types" ] + deps = [ "//ui/file_manager/file_manager/common/js:volume_manager_types" ] } js_library("path_component.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/path_component.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", ] extra_deps = [ ":modulize" ] @@ -1683,8 +1693,8 @@ js_library("providers_model") { js_library("providers_model.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/providers_model.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", ] @@ -1695,13 +1705,13 @@ js_unittest("providers_model_unittest.m") { deps = [ ":providers_model.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", "//ui/file_manager/file_manager/background/js:volume_info_impl.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] } @@ -1738,11 +1748,11 @@ js_library("quick_view_controller.m") { "ui:files_confirm_dialog.m", "ui:list_container.m", "ui:multi_menu_button.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:command_handler_deps.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:command_handler_deps.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/foreground/elements:files_quick_view.m", "//ui/file_manager/image_loader:image_loader_client.m", "//ui/file_manager/image_loader:load_image_request.m", @@ -1782,10 +1792,10 @@ js_library("quick_view_uma.m") { deps = [ ":dialog_type.m", ":file_tasks.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", ] @@ -1832,10 +1842,10 @@ js_library("search_controller.m") { "ui:file_manager_ui.m", "ui:location_line.m", "ui:search_box.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] extra_deps = [ ":modulize" ] @@ -1894,7 +1904,7 @@ js_unittest("spinner_controller_unittest.m") { deps = [ ":spinner_controller.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/webui/resources/js:assert.m", ] } @@ -1910,7 +1920,8 @@ js_library("task_controller") { "metadata:metadata_model", "ui:file_manager_ui", ] - externs_list = [ "//ui/file_manager/externs/background/progress_center.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/progress_center.js" ] } js_library("task_controller.m") { @@ -1926,10 +1937,10 @@ js_library("task_controller.m") { ":task_history.m", "metadata:metadata_model.m", "ui:file_manager_ui.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:crostini.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:crostini.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -1950,15 +1961,15 @@ js_unittest("task_controller_unittest.m") { "metadata:mock_metadata.m", "ui:file_manager_ui.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:progress_center.m", "//ui/file_manager/file_manager/background/js:mock_crostini.m", "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:progress_center.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr:ui.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -2007,8 +2018,8 @@ js_unittest("thumbnail_loader_unittest.m") { deps = [ ":thumbnail_loader.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/image_loader:image_loader_client.m", "//ui/file_manager/image_loader:load_image_request.m", ] @@ -2033,9 +2044,9 @@ js_library("toolbar_controller.m") { "ui:file_list_selection_model.m", "ui:list_container.m", "ui:location_line.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr/ui:command.m", @@ -2091,16 +2102,18 @@ js_test_gen_html("js_test_gen_html_modules") { ":thumbnail_loader_unittest.m", ] - closure_flags = - strict_error_checking_closure_args + [ - "generate_exports=false", - "js_module_root=./gen/ui", - "js_module_root=../../ui", - "jscomp_off=duplicate", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", - "hide_warnings_for=third_party/", - "hide_warnings_for=third_party/", - ] + closure_flags = strict_error_checking_closure_args + [ + "generate_exports=false", + "js_module_root=./gen/ui", + "js_module_root=../../ui/file_manager/", + "js_module_root=./gen/ui/file_manager/", + "jscomp_off=duplicate", + "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + "hide_warnings_for=third_party/", + "hide_warnings_for=third_party/", + ] } js_modulizer("modulize") { @@ -2181,6 +2194,13 @@ preprocess_folder = "$target_gen_dir/../../../preprocessed/file_manager/foreground/js", root_build_dir) +files_app_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/file_manager", + root_build_dir) +image_loader_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/image_loader", + root_build_dir) + optimize_webui("build") { host = "file_manager" @@ -2196,6 +2216,11 @@ optimize_webui("build") { "shared.m.rollup.js", ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":main.m", "//ui/file_manager:preprocess_generated", @@ -2212,6 +2237,11 @@ optimize_webui("build_worker") { js_out_files = [ "metadata_dispatcher.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ "metadata:metadata_dispatcher.m", "//ui/file_manager:preprocess_generated", 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 5205e2bbbcd..70e8512424b 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 @@ -21,6 +21,12 @@ group("closure_compile") { } js_type_check("closure_compile_jsmodules") { + closure_flags = default_closure_args + [ + "js_module_root=gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + ] + deps = [ ":byte_reader.m", ":content_metadata_provider.m", @@ -115,7 +121,7 @@ js_unittest("content_metadata_provider_unittest.m") { ":content_metadata_provider.m", ":metadata_request.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -133,7 +139,7 @@ js_library("exif_parser") { ":exif_constants", ":image_parsers", ] - externs_list = [ "//ui/file_manager/externs/exif_entry.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/exif_entry.js" ] } js_library("exif_parser.m") { @@ -142,8 +148,8 @@ js_library("exif_parser.m") { ":byte_reader.m", ":exif_constants.m", ":metadata_parser.m", - "//ui/file_manager/externs:exif_entry.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:exif_entry.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] extra_deps = [ ":modulize" ] @@ -155,15 +161,15 @@ js_unittest("exif_parser_unittest.m") { ":exif_constants.m", ":exif_parser.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/externs:exif_entry.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:exif_entry.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] } js_library("external_metadata_provider") { deps = [ ":metadata_provider", - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:file_manager_private", ] } @@ -173,7 +179,7 @@ js_library("external_metadata_provider.m") { ":metadata_item.m", ":metadata_provider.m", ":metadata_request.m", - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:file_manager_private", "//ui/webui/resources/js:assert.m", ] @@ -185,8 +191,8 @@ js_unittest("external_metadata_provider_unittest.m") { ":external_metadata_provider.m", ":metadata_request.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -209,7 +215,7 @@ js_unittest("file_system_metadata_provider_unittest.m") { ":file_system_metadata_provider.m", ":metadata_request.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -251,7 +257,7 @@ js_library("id3_parser.m") { ":function_parallel.m", ":function_sequence.m", ":metadata_parser.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] extra_deps = [ ":modulize" ] @@ -275,7 +281,8 @@ js_unittest("image_orientation_unittest.m") { js_library("image_parsers") { deps = [ ":metadata_parser" ] - externs_list = [ "//ui/file_manager/externs/metadata_worker_window.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/metadata_worker_window.js" ] } js_library("image_parsers.m") { @@ -283,7 +290,7 @@ js_library("image_parsers.m") { deps = [ ":byte_reader.m", ":metadata_parser.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] extra_deps = [ ":modulize" ] @@ -354,7 +361,7 @@ js_library("metadata_dispatcher") { ":metadata_parser", ":mpeg_parser", ] - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] } js_library("metadata_dispatcher.m") { @@ -365,9 +372,9 @@ js_library("metadata_dispatcher.m") { ":image_parsers.m", ":metadata_parser.m", ":mpeg_parser.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] extra_deps = [ ":modulize" ] } @@ -390,8 +397,8 @@ js_library("metadata_model") { ":metadata_item", ":metadata_provider", ":multi_metadata_provider", - "//ui/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/externs:volume_manager", ] } @@ -405,8 +412,8 @@ js_library("metadata_model.m") { ":metadata_item.m", ":metadata_provider.m", ":multi_metadata_provider.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] extra_deps = [ ":modulize" ] @@ -417,7 +424,7 @@ js_unittest("metadata_model_unittest.m") { ":metadata_model.m", ":metadata_provider.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -429,7 +436,7 @@ js_library("metadata_parser.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.m.js" ] deps = [ ":byte_reader.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] extra_deps = [ ":modulize" ] @@ -483,7 +490,7 @@ js_library("mpeg_parser.m") { deps = [ ":byte_reader.m", ":metadata_parser.m", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", ] extra_deps = [ ":modulize" ] @@ -495,7 +502,7 @@ js_library("multi_metadata_provider") { ":external_metadata_provider", ":file_system_metadata_provider", ":metadata_provider", - "//ui/file_manager/externs:volume_manager", + "//ui/file_manager/file_manager/externs:volume_manager", ] } @@ -508,8 +515,8 @@ js_library("multi_metadata_provider.m") { ":metadata_item.m", ":metadata_provider.m", ":metadata_request.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/webui/resources/js:assert.m", ] @@ -524,9 +531,9 @@ js_unittest("multi_metadata_provider_unittest.m") { ":metadata_request.m", ":multi_metadata_provider.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", ] } @@ -550,7 +557,7 @@ js_unittest("thumbnail_model_unittest.m") { ":metadata_model.m", ":thumbnail_model.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -569,13 +576,15 @@ js_test_gen_html("js_test_gen_html_modules") { ] js_module = true - closure_flags = - strict_error_checking_closure_args + [ - "js_module_root=./gen/ui", - "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", - "hide_warnings_for=third_party/", - ] + closure_flags = strict_error_checking_closure_args + [ + "js_module_root=./gen/ui", + "js_module_root=../../ui/file_manager/", + "js_module_root=./gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + "hide_warnings_for=third_party/", + ] } js_modulizer("modulize") { 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 dabe1d6c23b..d8662c3bc18 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 @@ -22,6 +22,12 @@ group("closure_compile") { js_type_check("closure_compile_jsmodules") { is_polymer3 = true + closure_flags = default_closure_args + [ + "js_module_root=gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + ] + deps = [ ":a11y_announce.m", ":action_model_ui.m", @@ -115,23 +121,23 @@ js_library("closure_compile_externs") { sources = [] externs_list = [ "$externs_path/metrics_private.js", - "//ui/file_manager/externs/background/crostini.js", - "//ui/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/externs/background/background_base.js", - "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/background/import_history.js", - "//ui/file_manager/externs/background_window.js", - "//ui/file_manager/externs/chrome_echo_private.js", - "//ui/file_manager/externs/chrome_webstore_widget_private.js", - "//ui/file_manager/externs/css_rule.js", - "//ui/file_manager/externs/drag_target.js", - "//ui/file_manager/externs/drive_dialog_controller.js", - "//ui/file_manager/externs/entries_changed_event.js", - "//ui/file_manager/externs/gallery_foreground.js", - "//ui/file_manager/externs/menu_item_update_event.js", - "//ui/file_manager/externs/paper_elements.js", - "//ui/file_manager/externs/platform.js", - "//ui/file_manager/externs/search_item.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", ] } @@ -197,14 +203,15 @@ js_unittest("actions_submenu_unittest.m") { js_library("banners") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/file_manager/file_manager/foreground/js:directory_model", "//ui/file_manager/file_manager/foreground/js:holding_space_util", "//ui/webui/resources/js:assert", "//ui/webui/resources/js/cr:event_target", ] - externs_list = [ "//ui/file_manager/externs/chrome_echo_private.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/chrome_echo_private.js" ] } js_library("banners.m") { @@ -212,10 +219,10 @@ js_library("banners.m") { "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/banners.m.js", ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.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/js:constants.m", "//ui/file_manager/file_manager/foreground/js:directory_model.m", "//ui/file_manager/file_manager/foreground/js:holding_space_util.m", @@ -255,7 +262,7 @@ js_library("combobutton") { ":multi_menu_button", "//ui/file_manager/file_manager/foreground/elements:files_toggle_ripple", ] - externs_list = [ "//ui/file_manager/externs/paper_elements.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/paper_elements.js" ] } js_library("combobutton.m") { @@ -268,7 +275,7 @@ js_library("combobutton.m") { "//ui/webui/resources/js/cr/ui:menu_item.m", ] - externs_list = [ "//ui/file_manager/externs/paper_elements.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/paper_elements.js" ] extra_deps = [ ":modulize" ] } @@ -341,8 +348,8 @@ js_library("dialog_footer.m") { js_library("directory_tree") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/file_manager/file_manager/foreground/js:directory_model", "//ui/file_manager/file_manager/foreground/js:navigation_list_model", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model", @@ -355,14 +362,14 @@ js_library("directory_tree") { js_library("directory_tree.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/directory_tree.m.js" ] deps = [ - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_info.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.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/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/foreground/js:constants.m", "//ui/file_manager/file_manager/foreground/js:directory_contents.m", "//ui/file_manager/file_manager/foreground/js:directory_model.m", @@ -375,7 +382,8 @@ js_library("directory_tree.m") { "//ui/webui/resources/js/cr/ui:menu.m", "//ui/webui/resources/js/cr/ui:tree.m", ] - visibility += [ "//ui/file_manager/externs:command_handler_deps.m" ] + visibility += + [ "//ui/file_manager/file_manager/externs:command_handler_deps.m" ] extra_deps = [ ":modulize" ] } @@ -384,14 +392,14 @@ js_unittest("directory_tree_unittest.m") { deps = [ ":directory_tree.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", - "//ui/file_manager/base/js:test_error_reporting.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/foreground/js:directory_model.m", "//ui/file_manager/file_manager/foreground/js:fake_android_app_list_model.m", "//ui/file_manager/file_manager/foreground/js:mock_directory_model.m", @@ -408,13 +416,13 @@ js_library("drag_selector") { "//ui/webui/resources/js/cr:ui", "//ui/webui/resources/js/cr/ui:list", ] - externs_list = [ "//ui/file_manager/externs/drag_target.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/drag_target.js" ] } js_library("drag_selector.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/drag_selector.m.js" ] deps = [ "//ui/webui/resources/js/cr/ui:list.m" ] - externs_list = [ "//ui/file_manager/externs/drag_target.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/drag_target.js" ] extra_deps = [ ":modulize" ] } @@ -442,7 +450,8 @@ js_library("file_grid") { "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model", "//ui/webui/resources/js/cr/ui:grid", ] - externs_list = [ "//ui/file_manager/externs/background/import_history.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/import_history.js" ] } js_library("file_grid.m") { @@ -452,13 +461,13 @@ js_library("file_grid.m") { ":drag_selector.m", ":file_table_list.m", ":file_tap_handler.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/foreground/js:list_thumbnail_loader.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", "//ui/webui/resources/js:assert.m", @@ -521,7 +530,7 @@ js_unittest("file_manager_dialog_base_unittest.m") { deps = [ ":file_manager_dialog_base.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/webui/resources/js:assert.m", ] } @@ -599,9 +608,9 @@ js_library("file_manager_ui.m") { ":progress_center_panel.m", ":providers_menu.m", ":search_box.m", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/foreground/elements:files_password_dialog.m", "//ui/file_manager/file_manager/foreground/elements:files_toast.m", "//ui/file_manager/file_manager/foreground/elements:files_tooltip.m", @@ -617,7 +626,8 @@ js_library("file_manager_ui.m") { "//ui/webui/resources/js/cr/ui:menu_item.m", "//ui/webui/resources/js/cr/ui:splitter.m", ] - visibility += [ "//ui/file_manager/externs:command_handler_deps.m" ] + visibility += + [ "//ui/file_manager/file_manager/externs:command_handler_deps.m" ] extra_deps = [ ":modulize" ] } @@ -651,7 +661,8 @@ js_library("file_table") { "//ui/file_manager/file_manager/foreground/js:list_thumbnail_loader", "//ui/webui/resources/js:cr", ] - externs_list = [ "//ui/file_manager/externs/background/import_history.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/background/import_history.js" ] } js_library("file_table.m") { @@ -666,14 +677,14 @@ js_library("file_table.m") { "table:table_column.m", "table:table_column_model.m", "table:table_list.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_manager.m", - "//ui/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/foreground/js:file_list_model.m", "//ui/file_manager/file_manager/foreground/js:list_thumbnail_loader.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", @@ -714,10 +725,10 @@ js_library("file_table_list.m") { ":file_list_selection_model.m", ":file_tap_handler.m", "table:table_list.m", - "//ui/file_manager/externs:entry_location.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/common/js:file_type.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:entry_location.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:cr.m", @@ -737,10 +748,10 @@ js_unittest("file_table_list_unittest.m") { ":file_table.m", ":file_table_list.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:volume_manager_types.m", - "//ui/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/background/js:mock_volume_manager.m", "//ui/file_manager/file_manager/common/js:files_app_entry_types.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", + "//ui/file_manager/file_manager/externs/background:import_history.m", "//ui/file_manager/file_manager/foreground/js:directory_model.m", "//ui/file_manager/file_manager/foreground/js:file_list_model.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model.m", @@ -763,7 +774,7 @@ js_unittest("file_tap_handler_unittest.m") { deps = [ ":file_tap_handler.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -805,7 +816,7 @@ js_library("files_menu") { "//ui/webui/resources/js/cr/ui:menu", "//ui/webui/resources/js/cr/ui:menu_item", ] - externs_list = [ "//ui/file_manager/externs/paper_elements.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/paper_elements.js" ] } js_library("files_menu.m") { @@ -815,7 +826,7 @@ js_library("files_menu.m") { "//ui/webui/resources/js/cr/ui:menu.m", "//ui/webui/resources/js/cr/ui:menu_item.m", ] - externs_list = [ "//ui/file_manager/externs/paper_elements.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/paper_elements.js" ] extra_deps = [ ":modulize" ] } @@ -914,11 +925,11 @@ js_library("list_container.m") { js_library("location_line") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/common/js:files_app_entry_types", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/foreground/js:path_component", ] } @@ -928,10 +939,10 @@ js_library("location_line.m") { deps = [ ":breadcrumb.m", ":list_container.m", - "//ui/file_manager/externs:files_app_entry_interfaces.m", - "//ui/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/common/js:metrics.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", + "//ui/file_manager/file_manager/externs:volume_manager.m", "//ui/file_manager/file_manager/foreground/elements:files_tooltip.m", "//ui/file_manager/file_manager/foreground/js:path_component.m", "//ui/webui/resources/js/cr:event_target.m", @@ -1013,15 +1024,16 @@ js_library("progress_center_panel") { visibility += [ "//ui/file_manager/file_manager/background/*" ] deps = [ "//ui/file_manager/file_manager/common/js:progress_center_common" ] - externs_list = [ "//ui/file_manager/externs/progress_center_panel.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/progress_center_panel.js" ] } js_library("progress_center_panel.m") { sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.m.js" ] deps = [ - "//ui/file_manager/externs:progress_center_panel.m", "//ui/file_manager/file_manager/common/js:progress_center_common.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs:progress_center_panel.m", "//ui/webui/resources/js:assert.m", ] @@ -1036,7 +1048,8 @@ js_library("providers_menu") { "//ui/webui/resources/js/cr/ui:menu", "//ui/webui/resources/js/cr/ui:position_util", ] - externs_list = [ "//ui/file_manager/externs/menu_item_update_event.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/menu_item_update_event.js" ] } js_library("providers_menu.m") { @@ -1065,7 +1078,7 @@ js_library("search_box") { "//ui/webui/resources/js/cr:event_target", "//ui/webui/resources/js/cr:ui", ] - externs_list = [ "//ui/file_manager/externs/search_item.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/search_item.js" ] } js_library("search_box.m") { @@ -1082,7 +1095,7 @@ js_library("search_box.m") { "//ui/webui/resources/js/cr:event_target.m", "//ui/webui/resources/js/cr/ui:list_item.m", ] - externs_list = [ "//ui/file_manager/externs/search_item.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/search_item.js" ] extra_deps = [ ":modulize" ] } @@ -1124,15 +1137,17 @@ js_test_gen_html("js_test_gen_html_modules") { ] is_polymer3 = true - closure_flags = - strict_error_checking_closure_args + [ - "generate_exports=false", - "js_module_root=./gen/ui", - "js_module_root=../../ui", - "jscomp_off=duplicate", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", - "hide_warnings_for=third_party/", - ] + closure_flags = strict_error_checking_closure_args + [ + "generate_exports=false", + "js_module_root=./gen/ui", + "js_module_root=../../ui/file_manager/", + "js_module_root=./gen/ui/file_manager/", + "jscomp_off=duplicate", + "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + "hide_warnings_for=third_party/", + ] } js_modulizer("modulize") { diff --git a/chromium/ui/file_manager/file_manager/test/BUILD.gn b/chromium/ui/file_manager/file_manager/test/BUILD.gn deleted file mode 100644 index e0e1a18ab7b..00000000000 --- a/chromium/ui/file_manager/file_manager/test/BUILD.gn +++ /dev/null @@ -1,106 +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") - -action("create_test_main") { - script = "//ui/file_manager/file_manager/test/scripts/create_test_main.py" - output = "$target_gen_dir/../test.html" - sources = [ - "//chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc", - "//ui/chromeos/file_manager_strings.grdp", - "//ui/file_manager/file_manager/background/js/background_common_scripts.js", - "//ui/file_manager/file_manager/background/js/background_scripts.js", - "//ui/file_manager/file_manager/foreground/elements/elements_bundle.html", - "//ui/file_manager/file_manager/foreground/elements/files_quick_view.html", - "//ui/file_manager/file_manager/foreground/elements/files_safe_media.html", - "//ui/file_manager/file_manager/foreground/elements/files_safe_media.js", - "//ui/file_manager/file_manager/foreground/js/elements_importer.js", - "//ui/file_manager/file_manager/foreground/js/main_scripts.js", - "//ui/file_manager/file_manager/main.html", - "check_select.js", - "crostini_mount.js", - "crostini_share.js", - "crostini_tasks.js", - "js/strings.js", - "menu.js", - ] - deps = [ "//ui/resources:webui_resources_grd" ] - args = [ "--output=" + rebase_path(output, root_build_dir) ] - outputs = [ output ] -} - -js_type_check("closure_compile") { - uses_legacy_modules = true - deps = [ - ":check_select", - ":closure_compile_externs", - ":crostini_mount", - ":crostini_share", - ":crostini_tasks", - ":menu", - ":plugin_vm", - ] -} - -# Remaining targets in this file are private. -visibility = [ ":*" ] - -js_library("closure_compile_externs") { - sources = [] - externs_list = [ - "js/externs.js", - "$externs_path/command_line_private.js", - "$externs_path/metrics_private.js", - "//ui/file_manager/externs/background/background_base.js", - "//ui/file_manager/externs/background/progress_center.js", - "//ui/file_manager/externs/background/crostini.js", - "//ui/file_manager/externs/entry_location.js", - "//ui/file_manager/externs/volume_info.js", - "//ui/file_manager/externs/volume_info_list.js", - "//ui/file_manager/externs/volume_manager.js", - ] -} - -js_library("check_select") { - deps = [ - "js:test_util", - "//ui/webui/resources/js:webui_resource_test", - ] -} - -js_library("crostini_mount") { - deps = [ - "js:test_util", - "//ui/webui/resources/js:webui_resource_test", - ] -} - -js_library("crostini_share") { - deps = [ - "js:test_util", - "//ui/webui/resources/js:webui_resource_test", - ] -} - -js_library("crostini_tasks") { - deps = [ - "js:test_util", - "//ui/webui/resources/js:webui_resource_test", - ] -} - -js_library("menu") { - deps = [ - "js:test_util", - "//ui/webui/resources/js:webui_resource_test", - ] -} - -js_library("plugin_vm") { - deps = [ - "js:test_util", - "//ui/webui/resources/js:webui_resource_test", - ] -} diff --git a/chromium/ui/file_manager/file_manager/test/js/BUILD.gn b/chromium/ui/file_manager/file_manager/test/js/BUILD.gn deleted file mode 100644 index 603e4503770..00000000000 --- a/chromium/ui/file_manager/file_manager/test/js/BUILD.gn +++ /dev/null @@ -1,30 +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") - -visibility = [ "//ui/file_manager/file_manager/*" ] - -js_library("chrome_api_test_impl") { -} - -js_library("chrome_file_manager_private_test_impl") { - deps = [ - ":chrome_api_test_impl", - "//ui/file_manager/file_manager/background/js:mock_volume_manager", - ] -} - -js_library("strings") { - deps = [ "//ui/webui/resources/js:load_time_data" ] -} - -js_library("test_util") { - deps = [ - ":chrome_file_manager_private_test_impl", - "//ui/file_manager/file_manager/background/js:runtime_loaded_test_util", - "//ui/file_manager/file_manager/foreground/js:constants", - "//ui/webui/resources/js:webui_resource_test", - ] -} diff --git a/chromium/ui/file_manager/gallery/js/BUILD.gn b/chromium/ui/file_manager/gallery/js/BUILD.gn index 4d1f700bdcb..1480d67d036 100644 --- a/chromium/ui/file_manager/gallery/js/BUILD.gn +++ b/chromium/ui/file_manager/gallery/js/BUILD.gn @@ -58,7 +58,7 @@ js_unittest("dimmable_ui_controller_unittest") { js_library("entry_list_watcher") { deps = [ - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:file_manager_private", "//ui/webui/resources/js:assert", "//ui/webui/resources/js/cr/ui:array_data_model", ] @@ -67,8 +67,8 @@ js_library("entry_list_watcher") { js_unittest("entry_list_watcher_unittest") { deps = [ ":entry_list_watcher", - "//ui/file_manager/base/js:test_error_reporting", "//ui/file_manager/file_manager/common/js:mock_entry", + "//ui/file_manager/file_manager/common/js:test_error_reporting", ] } @@ -81,8 +81,8 @@ js_library("gallery") { ":gallery_constants", ":gallery_item", ":thumbnail_mode", - "//ui/file_manager/base/js:app_util", - "//ui/file_manager/base/js:filtered_volume_manager", + "//ui/file_manager/file_manager/common/js:app_util", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager", "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/foreground/js/ui:files_confirm_dialog", "//ui/file_manager/gallery/js:slide_mode", @@ -108,7 +108,7 @@ js_unittest("gallery_data_model_unittest") { deps = [ ":gallery_data_model", ":mock_gallery_item", - "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/file_manager/common/js:test_error_reporting", ] } @@ -122,14 +122,14 @@ js_library("gallery_item") { "//ui/file_manager/file_manager/foreground/js/metadata:metadata_model", "//ui/file_manager/file_manager/foreground/js/metadata:thumbnail_model", ] - externs_list = [ "//ui/file_manager/externs/entry_location.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/entry_location.js" ] } js_unittest("gallery_item_unittest") { deps = [ ":gallery_item", ":mock_gallery_item", - "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/file_manager/common/js:test_error_reporting", ] } @@ -139,18 +139,18 @@ js_library("gallery_metrics") { js_library("gallery_util") { deps = [ - "//ui/file_manager/base/js:volume_manager_types", - "//ui/file_manager/externs:volume_manager", "//ui/file_manager/file_manager/common/js:file_type", "//ui/file_manager/file_manager/common/js:util", + "//ui/file_manager/file_manager/common/js:volume_manager_types", + "//ui/file_manager/file_manager/externs:volume_manager", ] } js_unittest("gallery_util_unittest") { deps = [ ":gallery_util", - "//ui/file_manager/base/js:test_error_reporting", "//ui/file_manager/file_manager/common/js:mock_entry", + "//ui/file_manager/file_manager/common/js:test_error_reporting", ] } @@ -203,13 +203,14 @@ js_library("slide_mode") { "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/foreground/elements:files_toggle_ripple", ] - externs_list = [ "//ui/file_manager/externs/gallery_foreground.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/gallery_foreground.js" ] } js_unittest("slide_mode_unittest") { deps = [ ":slide_mode", - "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/file_manager/common/js:test_error_reporting", ] } diff --git a/chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn b/chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn index e85237742a1..302085e8445 100644 --- a/chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn +++ b/chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn @@ -56,7 +56,7 @@ js_library("exif_encoder") { "//ui/file_manager/file_manager/foreground/js/metadata:exif_constants", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_item", ] - externs_list = [ "//ui/file_manager/externs/exif_entry.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/exif_entry.js" ] } js_library("exif_encoder.m") { @@ -65,7 +65,7 @@ js_library("exif_encoder.m") { ] deps = [ ":image_encoder.m", - "//ui/file_manager/externs:exif_entry.m", + "//ui/file_manager/file_manager/externs:exif_entry.m", "//ui/file_manager/file_manager/foreground/js/metadata:exif_constants.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_item.m", "//ui/webui/resources/js:assert.m", @@ -80,7 +80,7 @@ js_unittest("exif_encoder_unittest.m") { ":image_encoder.m", ":test_util.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/externs:metadata_worker_window.m", + "//ui/file_manager/file_manager/externs:metadata_worker_window.m", "//ui/file_manager/file_manager/foreground/js/metadata:byte_reader.m", "//ui/file_manager/file_manager/foreground/js/metadata:exif_parser.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_item.m", @@ -136,7 +136,7 @@ js_library("image_editor_toolbar") { "//ui/file_manager/file_manager/foreground/elements:files_tooltip", "//ui/file_manager/gallery/js/:gallery_util", ] - externs_list = [ "//ui/file_manager/externs/paper_elements.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/paper_elements.js" ] } js_library("image_encoder") { @@ -165,10 +165,11 @@ js_unittest("image_encoder_unittest.m") { ":image_encoder.m", ":test_util.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", "//ui/file_manager/file_manager/foreground/js/metadata:metadata_item.m", ] - externs_list = [ "//ui/file_manager/externs/metadata_worker_window.js" ] + externs_list = + [ "//ui/file_manager/file_manager/externs/metadata_worker_window.js" ] } js_library("image_loader") { diff --git a/chromium/ui/file_manager/image_loader/BUILD.gn b/chromium/ui/file_manager/image_loader/BUILD.gn index 41c22b230aa..fe3ac7da91b 100644 --- a/chromium/ui/file_manager/image_loader/BUILD.gn +++ b/chromium/ui/file_manager/image_loader/BUILD.gn @@ -9,6 +9,11 @@ import("//ui/file_manager/base/gn/js_test_gen_html.gni") import("//ui/webui/resources/tools/js_modulizer.gni") js_type_check("closure_compile_jsmodules") { + closure_flags = default_closure_args + [ + "jscomp_error=strictCheckTypes", + "js_module_root=gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + ] deps = [ ":background.m", ":cache.m", @@ -62,7 +67,7 @@ js_library("image_loader") { ":image_request_task", ":load_image_request", ":scheduler", - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/externs:file_manager_private", ] } @@ -158,7 +163,7 @@ js_unittest("image_loader_client_unittest.m") { ":image_loader_client.m", ":load_image_request.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/file_manager/common/js:test_error_reporting.m", ] } @@ -166,12 +171,12 @@ js_library("piex_loader") { # No dependencies should be added here, so the module can be loaded as a # standalone .js file. - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] } js_library("piex_loader.m") { sources = [ "$root_gen_dir/ui/file_manager/image_loader/piex_loader.m.js" ] - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] extra_deps = [ ":modulize" ] } @@ -184,7 +189,7 @@ js_library("image_request_task") { ":piex_loader", "//ui/file_manager/file_manager/common/js:file_type", ] - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] } js_library("image_request_task.m") { @@ -231,12 +236,13 @@ js_test_gen_html("js_test_gen_html_modules") { ] js_module = true - closure_flags = - strict_error_checking_closure_args + [ - "js_module_root=./gen/ui", - "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", - ] + closure_flags = strict_error_checking_closure_args + [ + "js_module_root=./gen/ui", + "js_module_root=../../ui/file_manager/", + "js_module_root=./gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + ] } group("closure_compile") { @@ -264,6 +270,13 @@ js_modulizer("modulize") { preprocess_folder = rebase_path("$target_gen_dir/../preprocessed/image_loader", root_build_dir) +files_app_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/file_manager", + root_build_dir) +image_loader_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/image_loader", + root_build_dir) + optimize_webui("build") { host = "image_loader" @@ -272,6 +285,11 @@ optimize_webui("build") { js_out_files = [ "background.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":background.m", "//ui/file_manager:preprocess_generated", diff --git a/chromium/ui/file_manager/integration_tests/BUILD.gn b/chromium/ui/file_manager/integration_tests/BUILD.gn index 60f6800ddcc..10d426fbe1d 100644 --- a/chromium/ui/file_manager/integration_tests/BUILD.gn +++ b/chromium/ui/file_manager/integration_tests/BUILD.gn @@ -10,7 +10,7 @@ js_type_check("closure_compile") { deps = [ ":remote_call", ":test_util", - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", ] } 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 96280284ca7..7f963c8a048 100644 --- a/chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn +++ b/chromium/ui/file_manager/integration_tests/file_manager/BUILD.gn @@ -8,6 +8,7 @@ js_type_check("closure_compile") { uses_legacy_modules = true testonly = true deps = [ + ":android_photos", ":background", ":breadcrumbs", ":context_menu", @@ -55,12 +56,17 @@ js_type_check("closure_compile") { js_library("background") { testonly = true deps = [ - "//ui/file_manager/base/js:volume_manager_types", + "//ui/file_manager/file_manager/common/js:volume_manager_types", "//ui/file_manager/integration_tests:remote_call", "//ui/file_manager/integration_tests:test_util", ] } +js_library("android_photos") { + testonly = true + deps = [ ":background" ] +} + js_library("breadcrumbs") { 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 ad25c71b9d9..179d4d920ec 100644 --- a/chromium/ui/file_manager/video_player/js/BUILD.gn +++ b/chromium/ui/file_manager/video_player/js/BUILD.gn @@ -19,6 +19,11 @@ group("closure_compile") { js_type_check("closure_compile_jsmodules") { is_polymer3 = true + closure_flags = default_closure_args + [ + "js_module_root=gen/ui/file_manager/", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + ] deps = [ ":background.m", ":error_util.m", @@ -49,8 +54,8 @@ js_library("closure_compile_externs") { "$externs_path/media_player_private.js", "$externs_path/metrics_private.js", "$externs_path/picture_in_picture.js", - "//ui/file_manager/externs/chrome_cast.js", - "//ui/file_manager/externs/platform.js", + "//ui/file_manager/file_manager/externs/chrome_cast.js", + "//ui/file_manager/file_manager/externs/platform.js", ] } @@ -65,10 +70,10 @@ js_library("background") { js_library("background.m") { sources = [ "$root_gen_dir/ui/file_manager/video_player/js/background.m.js" ] deps = [ - "//ui/file_manager/externs/background:background_base.m", "//ui/file_manager/file_manager/background/js:app_window_wrapper.m", "//ui/file_manager/file_manager/background/js:background_base.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/externs/background:background_base.m", "//ui/webui/resources/js:assert.m", ] @@ -99,25 +104,25 @@ js_library("test_util.m") { js_library("video_player_native_controls") { deps = [ - "//ui/file_manager/base/js:app_util", - "//ui/file_manager/externs:file_manager_private", + "//ui/file_manager/file_manager/common/js:app_util", + "//ui/file_manager/file_manager/externs:file_manager_private", "//ui/webui/resources/js:load_time_data", "//ui/webui/resources/js:util", ] - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] } js_library("video_player_native_controls.m") { sources = [ "$root_gen_dir/ui/file_manager/video_player/js/video_player_native_controls.m.js" ] deps = [ - "//ui/file_manager/base/js:app_util.m", + "//ui/file_manager/file_manager/common/js:app_util.m", "//ui/webui/resources/cr_elements/cr_toast:cr_toast.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js:util.m", ] - externs_list = [ "//ui/file_manager/externs/platform.js" ] + externs_list = [ "//ui/file_manager/file_manager/externs/platform.js" ] extra_deps = [ ":modulize" ] } @@ -126,7 +131,7 @@ js_unittest("video_player_native_controls_unittest.m") { deps = [ ":video_player_native_controls.m", "//chrome/test/data/webui:chai_assert", - "//ui/file_manager/base/js:mock_chrome.m", + "//ui/file_manager/file_manager/common/js:mock_chrome.m", ] } @@ -135,8 +140,8 @@ js_library("video_player") { ":error_util", ":video_player_metrics", ":video_player_native_controls", - "//ui/file_manager/base/js:app_util", - "//ui/file_manager/base/js:filtered_volume_manager", + "//ui/file_manager/file_manager/common/js:app_util", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager", "//ui/file_manager/file_manager/common/js:metrics_base", "//ui/file_manager/file_manager/common/js:util", "//ui/webui/resources/js/cr/ui:menu", @@ -151,10 +156,10 @@ js_library("video_player.m") { ":error_util.m", ":video_player_metrics.m", ":video_player_native_controls.m", - "//ui/file_manager/base/js:app_util.m", - "//ui/file_manager/base/js:filtered_volume_manager.m", - "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/file_manager/common/js:app_util.m", + "//ui/file_manager/file_manager/common/js:filtered_volume_manager.m", "//ui/file_manager/file_manager/common/js:util.m", + "//ui/file_manager/file_manager/common/js:volume_manager_types.m", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -179,14 +184,16 @@ js_test_gen_html("js_test_gen_html_modules") { deps = [ ":video_player_native_controls_unittest.m" ] is_polymer3 = true - closure_flags = - strict_error_checking_closure_args + [ - "generate_exports=false", - "js_module_root=./gen/ui", - "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", - "hide_warnings_for=third_party/", - ] + closure_flags = strict_error_checking_closure_args + [ + "generate_exports=false", + "js_module_root=gen/ui/file_manager/", + "js_module_root=./gen/ui", + "js_module_root=../../ui", + "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", + "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", + "hide_warnings_for=third_party/", + ] } js_library("main.m") { @@ -217,6 +224,13 @@ preprocess_folder = rebase_path("$target_gen_dir/../../preprocessed/video_player/js", root_build_dir) +files_app_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/file_manager", + root_build_dir) +image_loader_path = + rebase_path("$root_gen_dir/ui/file_manager/preprocessed/image_loader", + root_build_dir) + optimize_webui("build") { host = "video_player" @@ -225,6 +239,11 @@ optimize_webui("build") { js_out_files = [ "main.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":main.m", "//ui/file_manager:preprocess_generated", @@ -241,6 +260,11 @@ optimize_webui("build_background") { js_out_files = [ "main_background.m.rollup.js" ] + external_paths = [ + "chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj|$files_app_path", + "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp|$image_loader_path", + ] + deps = [ ":main_background.m", "//ui/file_manager:preprocess_generated", diff --git a/chromium/ui/gfx/BUILD.gn b/chromium/ui/gfx/BUILD.gn index 76622085d42..181c0c58918 100644 --- a/chromium/ui/gfx/BUILD.gn +++ b/chromium/ui/gfx/BUILD.gn @@ -75,6 +75,10 @@ component("gfx") { "color_transform.h", "decorated_text.cc", "decorated_text.h", + "delegated_ink_metadata.cc", + "delegated_ink_metadata.h", + "delegated_ink_point.cc", + "delegated_ink_point.h", "extension_set.cc", "extension_set.h", "favicon_size.cc", @@ -310,6 +314,7 @@ component("gfx") { "//base/third_party/dynamic_annotations", "//build:chromeos_buildflags", "//device/vr/buildflags", + "//mojo/public/cpp/bindings:struct_traits", "//skia", "//third_party/zlib", ] @@ -923,6 +928,7 @@ test("gfx_unittests") { if (is_android) { generate_jni("gfx_jni_headers") { sources = [ + "../android/java/src/org/chromium/ui/gfx/AdpfRenderingStageScheduler.java", "../android/java/src/org/chromium/ui/gfx/Animation.java", "../android/java/src/org/chromium/ui/gfx/BitmapHelper.java", "../android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java", diff --git a/chromium/ui/gfx/DEPS b/chromium/ui/gfx/DEPS index b58bc04323c..26e17db51af 100644 --- a/chromium/ui/gfx/DEPS +++ b/chromium/ui/gfx/DEPS @@ -11,3 +11,9 @@ include_rules = [ "-testing/gmock", ] + +specific_include_rules = { + "delegated_ink_point\.h" : [ + "+mojo/public/cpp/bindings/struct_traits.h", + ], +} diff --git a/chromium/ui/gfx/animation/keyframe/BUILD.gn b/chromium/ui/gfx/animation/keyframe/BUILD.gn index d49e3855f78..de625052238 100644 --- a/chromium/ui/gfx/animation/keyframe/BUILD.gn +++ b/chromium/ui/gfx/animation/keyframe/BUILD.gn @@ -26,6 +26,7 @@ component("keyframe") { "keyframe_effect.h", "keyframe_model.cc", "keyframe_model.h", + "keyframed_animation_curve-inl.h", "keyframed_animation_curve.cc", "keyframed_animation_curve.h", "target_property.h", diff --git a/chromium/ui/gfx/animation/keyframe/animation_curve.cc b/chromium/ui/gfx/animation/keyframe/animation_curve.cc index 645225d6031..17fcc23cf2e 100644 --- a/chromium/ui/gfx/animation/keyframe/animation_curve.cc +++ b/chromium/ui/gfx/animation/keyframe/animation_curve.cc @@ -44,5 +44,6 @@ DEFINE_ANIMATION_CURVE(Transform, TRANSFORM) DEFINE_ANIMATION_CURVE(Float, FLOAT) DEFINE_ANIMATION_CURVE(Size, SIZE) DEFINE_ANIMATION_CURVE(Color, COLOR) +DEFINE_ANIMATION_CURVE(Rect, RECT) } // namespace gfx diff --git a/chromium/ui/gfx/animation/keyframe/animation_curve.h b/chromium/ui/gfx/animation/keyframe/animation_curve.h index 8d119bf8862..bffb4c727b4 100644 --- a/chromium/ui/gfx/animation/keyframe/animation_curve.h +++ b/chromium/ui/gfx/animation/keyframe/animation_curve.h @@ -10,6 +10,7 @@ #include "base/time/time.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/animation/keyframe/keyframe_animation_export.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/transform.h" #include "ui/gfx/transform_operations.h" @@ -31,13 +32,11 @@ class GFX_KEYFRAME_ANIMATION_EXPORT AnimationCurve { FLOAT, TRANSFORM, SIZE, + RECT, // cc:: curve types. FILTER, SCROLL_OFFSET, - - // This must be last - LAST_CURVE_TYPE = SIZE, }; virtual ~AnimationCurve() = default; @@ -104,6 +103,10 @@ class GFX_KEYFRAME_ANIMATION_EXPORT TransformAnimationCurve DECLARE_ANIMATION_CURVE_BODY(gfx::TransformOperations, Transform) }; +class GFX_KEYFRAME_ANIMATION_EXPORT RectAnimationCurve : public AnimationCurve { + DECLARE_ANIMATION_CURVE_BODY(gfx::Rect, Rect) +}; + } // namespace gfx #endif // UI_GFX_ANIMATION_KEYFRAME_ANIMATION_CURVE_H_ diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc b/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc index 84b0f11327e..53bdb43d332 100644 --- a/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc +++ b/chromium/ui/gfx/animation/keyframe/keyframe_effect.cc @@ -208,25 +208,43 @@ void KeyframeEffect::AddKeyframeModel( } void KeyframeEffect::RemoveKeyframeModel(int keyframe_model_id) { - base::EraseIf(keyframe_models_, - [keyframe_model_id]( - const std::unique_ptr& keyframe_model) { - return keyframe_model->id() == keyframe_model_id; - }); + // Since we want to use the KeyframeModels that we're going to remove, we + // need to use a stable_partition here instead of remove_if. remove_if leaves + // the removed items in an unspecified state. + auto keyframe_models_to_remove = std::stable_partition( + keyframe_models_.begin(), keyframe_models_.end(), + [keyframe_model_id]( + const std::unique_ptr& keyframe_model) { + return keyframe_model->id() != keyframe_model_id; + }); + + RemoveKeyframeModelRange(keyframe_models_to_remove, keyframe_models_.end()); } void KeyframeEffect::RemoveKeyframeModels(int target_property) { - base::EraseIf( - keyframe_models_, - [target_property](const std::unique_ptr& keyframe_model) { - return keyframe_model->TargetProperty() == target_property; + auto keyframe_models_to_remove = std::stable_partition( + keyframe_models_.begin(), keyframe_models_.end(), + [target_property]( + const std::unique_ptr& keyframe_model) { + return keyframe_model->TargetProperty() != target_property; }); + RemoveKeyframeModelRange(keyframe_models_to_remove, keyframe_models_.end()); +} + +void KeyframeEffect::RemoveAllKeyframeModels() { + RemoveKeyframeModelRange(keyframe_models_.begin(), keyframe_models_.end()); } void KeyframeEffect::Tick(base::TimeTicks monotonic_time) { TickInternal(monotonic_time, true); } +void KeyframeEffect::RemoveKeyframeModelRange( + typename KeyframeModels::iterator to_remove_begin, + typename KeyframeModels::iterator to_remove_end) { + keyframe_models_.erase(to_remove_begin, to_remove_end); +} + void KeyframeEffect::TickKeyframeModel(base::TimeTicks monotonic_time, KeyframeModel* keyframe_model) { if ((keyframe_model->run_state() != KeyframeModel::STARTING && @@ -331,6 +349,10 @@ bool KeyframeEffect::IsAnimatingProperty(int property) const { return false; } +bool KeyframeEffect::IsAnimating() const { + return !keyframe_models_.empty(); +} + float KeyframeEffect::GetTargetFloatValue(int target_property, float default_value) const { return GetTargetValue(target_property, default_value); @@ -392,21 +414,26 @@ KeyframeModel* KeyframeEffect::GetRunningKeyframeModelForProperty( return nullptr; } -KeyframeModel* KeyframeEffect::GetKeyframeModelForProperty( - int target_property) const { - for (auto& keyframe_model : keyframe_models_) { - if (keyframe_model->TargetProperty() == target_property) { - return keyframe_model.get(); - } +KeyframeModel* KeyframeEffect::GetKeyframeModel(int target_property) const { + for (size_t i = 0; i < keyframe_models().size(); ++i) { + size_t index = keyframe_models().size() - i - 1; + if (keyframe_models_[index]->TargetProperty() == target_property) + return keyframe_models_[index].get(); } return nullptr; } +KeyframeModel* KeyframeEffect::GetKeyframeModelById(int id) const { + for (auto& keyframe_model : keyframe_models()) + if (keyframe_model->id() == id) + return keyframe_model.get(); + return nullptr; +} + template ValueType KeyframeEffect::GetTargetValue(int target_property, const ValueType& default_value) const { - KeyframeModel* running_keyframe_model = - GetKeyframeModelForProperty(target_property); + KeyframeModel* running_keyframe_model = GetKeyframeModel(target_property); if (!running_keyframe_model) { return default_value; } diff --git a/chromium/ui/gfx/animation/keyframe/keyframe_effect.h b/chromium/ui/gfx/animation/keyframe/keyframe_effect.h index 6894cadaa93..416055403e9 100644 --- a/chromium/ui/gfx/animation/keyframe/keyframe_effect.h +++ b/chromium/ui/gfx/animation/keyframe/keyframe_effect.h @@ -43,17 +43,19 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframeEffect { KeyframeEffect(const KeyframeEffect&) = delete; KeyframeEffect& operator=(const KeyframeEffect&) = delete; - void AddKeyframeModel(std::unique_ptr keyframe_model); + virtual void AddKeyframeModel(std::unique_ptr keyframe_model); + void RemoveAllKeyframeModels(); void RemoveKeyframeModel(int keyframe_model_id); void RemoveKeyframeModels(int target_property); - void Tick(base::TimeTicks monotonic_time); + virtual void Tick(base::TimeTicks monotonic_time); // This ticks all keyframe models until they are complete. void FinishAll(); using KeyframeModels = std::vector>; - const KeyframeModels& keyframe_models() { return keyframe_models_; } + const KeyframeModels& keyframe_models() const { return keyframe_models_; } + KeyframeModels& keyframe_models() { return keyframe_models_; } // The transition is analogous to CSS transitions. When configured, the // transition object will cause subsequent calls the corresponding @@ -88,6 +90,7 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframeEffect { SkColor to); bool IsAnimatingProperty(int property) const; + bool IsAnimating() const; float GetTargetFloatValue(int target_property, float default_value) const; gfx::TransformOperations GetTargetTransformOperationsValue( @@ -97,15 +100,24 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframeEffect { const gfx::SizeF& default_value) const; SkColor GetTargetColorValue(int target_property, SkColor default_value) const; KeyframeModel* GetRunningKeyframeModelForProperty(int target_property) const; - - private: + KeyframeModel* GetKeyframeModel(int target_property) const; + KeyframeModel* GetKeyframeModelById(int id) const; + + protected: + // Removes all keyframe models in the range provided. This is virtual so that + // subclasses that need to do extra bookkeeping upon removals may do so. As a + // consequence, please ensure that all removals happen via this method. + virtual void RemoveKeyframeModelRange( + typename KeyframeModels::iterator to_remove_begin, + typename KeyframeModels::iterator to_remove_end); void TickKeyframeModel(base::TimeTicks monotonic_time, KeyframeModel* keyframe_model); + + private: void TickInternal(base::TimeTicks monotonic_time, bool include_infinite_animations); void StartKeyframeModels(base::TimeTicks monotonic_time, bool include_infinite_animations); - KeyframeModel* GetKeyframeModelForProperty(int target_property) const; template ValueType GetTargetValue(int target_property, const ValueType& default_value) const; diff --git a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve-inl.h b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve-inl.h new file mode 100644 index 00000000000..ac226f6c7f5 --- /dev/null +++ b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve-inl.h @@ -0,0 +1,148 @@ +// 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_ANIMATION_KEYFRAME_KEYFRAMED_ANIMATION_CURVE_INL_H_ +#define UI_GFX_ANIMATION_KEYFRAME_KEYFRAMED_ANIMATION_CURVE_INL_H_ + +namespace { + +template +void InsertKeyframe(std::unique_ptr keyframe, + std::vector>* keyframes) { + // Usually, the keyframes will be added in order, so this loop would be + // unnecessary and we should skip it if possible. + if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) { + for (size_t i = 0; i < keyframes->size(); ++i) { + if (keyframe->Time() < keyframes->at(i)->Time()) { + keyframes->insert(keyframes->begin() + i, std::move(keyframe)); + return; + } + } + } + + keyframes->push_back(std::move(keyframe)); +} + +struct TimeValues { + base::TimeDelta start_time; + base::TimeDelta duration; + double progress; +}; + +template +TimeValues GetTimeValues(const KeyframeType& start_frame, + const KeyframeType& end_frame, + double scaled_duration, + base::TimeDelta time) { + TimeValues values; + values.start_time = start_frame.Time() * scaled_duration; + values.duration = (end_frame.Time() * scaled_duration) - values.start_time; + const base::TimeDelta elapsed = time - values.start_time; + values.progress = (elapsed.is_inf() || values.duration.is_zero()) + ? 1.0 + : (elapsed / values.duration); + return values; +} + +template +base::TimeDelta TransformedAnimationTime( + const std::vector>& keyframes, + const std::unique_ptr& timing_function, + double scaled_duration, + base::TimeDelta time) { + if (timing_function) { + const auto values = GetTimeValues(*keyframes.front(), *keyframes.back(), + scaled_duration, time); + time = (values.duration * timing_function->GetValue(values.progress)) + + values.start_time; + } + + return time; +} + +template +size_t GetActiveKeyframe( + const std::vector>& keyframes, + double scaled_duration, + base::TimeDelta time) { + DCHECK_GE(keyframes.size(), 2ul); + size_t i = 0; + while ((i < keyframes.size() - 2) && // Last keyframe is never active. + (time >= (keyframes[i + 1]->Time() * scaled_duration))) + ++i; + + return i; +} + +template +double TransformedKeyframeProgress( + const std::vector>& keyframes, + double scaled_duration, + base::TimeDelta time, + size_t i) { + const double progress = + GetTimeValues(*keyframes[i], *keyframes[i + 1], scaled_duration, time) + .progress; + return keyframes[i]->timing_function() + ? keyframes[i]->timing_function()->GetValue(progress) + : progress; +} + +int GetTimingFunctionSteps(const gfx::TimingFunction* timing_function) { + DCHECK(timing_function && + timing_function->GetType() == gfx::TimingFunction::Type::STEPS); + const gfx::StepsTimingFunction* steps_timing_function = + reinterpret_cast(timing_function); + DCHECK(steps_timing_function); + return steps_timing_function->steps(); +} + +template +base::TimeDelta ComputeTickInterval( + const std::unique_ptr& timing_function, + double scaled_duration, + const std::vector>& keyframes) { + // TODO(crbug.com/1140603): include animation progress in order to pinpoint + // which keyframe's timing function is in effect at any point in time. + DCHECK_LT(0u, keyframes.size()); + gfx::TimingFunction::Type timing_function_type = + timing_function ? timing_function->GetType() + : gfx::TimingFunction::Type::LINEAR; + // Even if the keyframe's have step timing functions, a non-linear + // animation-wide timing function results in unevenly timed steps. + switch (timing_function_type) { + case gfx::TimingFunction::Type::LINEAR: { + base::TimeDelta min_interval = base::TimeDelta::Max(); + // If any keyframe uses non-step "easing", return 0, except for the last + // keyframe, whose "easing" is never used. + for (size_t ii = 0; ii < keyframes.size() - 1; ++ii) { + KeyframeType* keyframe = keyframes[ii].get(); + if (!keyframe->timing_function() || + keyframe->timing_function()->GetType() != + gfx::TimingFunction::Type::STEPS) { + return base::TimeDelta(); + } + KeyframeType* next_keyframe = keyframes[ii + 1].get(); + int steps = GetTimingFunctionSteps(keyframe->timing_function()); + DCHECK_LT(0, steps); + base::TimeDelta interval = (next_keyframe->Time() - keyframe->Time()) * + scaled_duration / steps; + if (interval < min_interval) + min_interval = interval; + } + return min_interval; + } + case gfx::TimingFunction::Type::STEPS: { + return (keyframes.back()->Time() - keyframes.front()->Time()) * + scaled_duration / GetTimingFunctionSteps(timing_function.get()); + } + case gfx::TimingFunction::Type::CUBIC_BEZIER: + break; + } + return base::TimeDelta(); +} + +} // namespace + +#endif // UI_GFX_ANIMATION_KEYFRAME_KEYFRAMED_ANIMATION_CURVE_INL_H_ diff --git a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc index 6ff33616160..90671be1822 100644 --- a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc +++ b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.cc @@ -11,151 +11,12 @@ #include #include "base/memory/ptr_util.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 { - -template -void InsertKeyframe(std::unique_ptr keyframe, - std::vector>* keyframes) { - // Usually, the keyframes will be added in order, so this loop would be - // unnecessary and we should skip it if possible. - if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) { - for (size_t i = 0; i < keyframes->size(); ++i) { - if (keyframe->Time() < keyframes->at(i)->Time()) { - keyframes->insert(keyframes->begin() + i, std::move(keyframe)); - return; - } - } - } - - keyframes->push_back(std::move(keyframe)); -} - -struct TimeValues { - base::TimeDelta start_time; - base::TimeDelta duration; - double progress; -}; - -template -TimeValues GetTimeValues(const KeyframeType& start_frame, - const KeyframeType& end_frame, - double scaled_duration, - base::TimeDelta time) { - TimeValues values; - values.start_time = start_frame.Time() * scaled_duration; - values.duration = (end_frame.Time() * scaled_duration) - values.start_time; - const base::TimeDelta elapsed = time - values.start_time; - values.progress = (elapsed.is_inf() || values.duration.is_zero()) - ? 1.0 - : (elapsed / values.duration); - return values; -} - -template -base::TimeDelta TransformedAnimationTime( - const std::vector>& keyframes, - const std::unique_ptr& timing_function, - double scaled_duration, - base::TimeDelta time) { - if (timing_function) { - const auto values = GetTimeValues(*keyframes.front(), *keyframes.back(), - scaled_duration, time); - time = (values.duration * timing_function->GetValue(values.progress)) + - values.start_time; - } - - return time; -} - -template -size_t GetActiveKeyframe( - const std::vector>& keyframes, - double scaled_duration, - base::TimeDelta time) { - DCHECK_GE(keyframes.size(), 2ul); - size_t i = 0; - while ((i < keyframes.size() - 2) && // Last keyframe is never active. - (time >= (keyframes[i + 1]->Time() * scaled_duration))) - ++i; - - return i; -} - -template -double TransformedKeyframeProgress( - const std::vector>& keyframes, - double scaled_duration, - base::TimeDelta time, - size_t i) { - const double progress = - GetTimeValues(*keyframes[i], *keyframes[i + 1], scaled_duration, time) - .progress; - return keyframes[i]->timing_function() - ? keyframes[i]->timing_function()->GetValue(progress) - : progress; -} - -int GetTimingFunctionSteps(const TimingFunction* timing_function) { - DCHECK(timing_function && - timing_function->GetType() == TimingFunction::Type::STEPS); - const StepsTimingFunction* steps_timing_function = - reinterpret_cast(timing_function); - DCHECK(steps_timing_function); - return steps_timing_function->steps(); -} - -template -base::TimeDelta ComputeTickInterval( - const std::unique_ptr& timing_function, - double scaled_duration, - const std::vector>& keyframes) { - // TODO(crbug.com/1140603): include animation progress in order to pinpoint - // which keyframe's timing function is in effect at any point in time. - DCHECK_LT(0u, keyframes.size()); - TimingFunction::Type timing_function_type = - timing_function ? timing_function->GetType() - : TimingFunction::Type::LINEAR; - // Even if the keyframe's have step timing functions, a non-linear - // animation-wide timing function results in unevenly timed steps. - switch (timing_function_type) { - case TimingFunction::Type::LINEAR: { - base::TimeDelta min_interval = base::TimeDelta::Max(); - // If any keyframe uses non-step "easing", return 0, except for the last - // keyframe, whose "easing" is never used. - for (size_t ii = 0; ii < keyframes.size() - 1; ++ii) { - KeyframeType* keyframe = keyframes[ii].get(); - if (!keyframe->timing_function() || - keyframe->timing_function()->GetType() != - TimingFunction::Type::STEPS) { - return base::TimeDelta(); - } - KeyframeType* next_keyframe = keyframes[ii + 1].get(); - int steps = GetTimingFunctionSteps(keyframe->timing_function()); - DCHECK_LT(0, steps); - base::TimeDelta interval = (next_keyframe->Time() - keyframe->Time()) * - scaled_duration / steps; - if (interval < min_interval) - min_interval = interval; - } - return min_interval; - } - case TimingFunction::Type::STEPS: { - return (keyframes.back()->Time() - keyframes.front()->Time()) * - scaled_duration / GetTimingFunctionSteps(timing_function.get()); - } - case TimingFunction::Type::CUBIC_BEZIER: - break; - } - return base::TimeDelta(); -} - -} // namespace - Keyframe::Keyframe(base::TimeDelta time, std::unique_ptr timing_function) : time_(time), timing_function_(std::move(timing_function)) {} @@ -271,6 +132,32 @@ std::unique_ptr SizeKeyframe::Clone() const { return SizeKeyframe::Create(Time(), Value(), std::move(func)); } +std::unique_ptr RectKeyframe::Create( + base::TimeDelta time, + const gfx::Rect& value, + std::unique_ptr timing_function) { + return base::WrapUnique( + new RectKeyframe(time, value, std::move(timing_function))); +} + +RectKeyframe::RectKeyframe(base::TimeDelta time, + const gfx::Rect& value, + std::unique_ptr timing_function) + : Keyframe(time, std::move(timing_function)), value_(value) {} + +RectKeyframe::~RectKeyframe() = default; + +const gfx::Rect& RectKeyframe::Value() const { + return value_; +} + +std::unique_ptr RectKeyframe::Clone() const { + std::unique_ptr func; + if (timing_function()) + func = timing_function()->Clone(); + return RectKeyframe::Create(Time(), Value(), std::move(func)); +} + std::unique_ptr KeyframedColorAnimationCurve::Create() { return base::WrapUnique(new KeyframedColorAnimationCurve); @@ -512,4 +399,59 @@ gfx::SizeF KeyframedSizeAnimationCurve::GetValue(base::TimeDelta t) const { keyframes_[i + 1]->Value()); } +std::unique_ptr +KeyframedRectAnimationCurve::Create() { + return base::WrapUnique(new KeyframedRectAnimationCurve); +} + +KeyframedRectAnimationCurve::KeyframedRectAnimationCurve() + : scaled_duration_(1.0) {} + +KeyframedRectAnimationCurve::~KeyframedRectAnimationCurve() = default; + +void KeyframedRectAnimationCurve::AddKeyframe( + std::unique_ptr keyframe) { + InsertKeyframe(std::move(keyframe), &keyframes_); +} + +base::TimeDelta KeyframedRectAnimationCurve::Duration() const { + return (keyframes_.back()->Time() - keyframes_.front()->Time()) * + scaled_duration(); +} + +base::TimeDelta KeyframedRectAnimationCurve::TickInterval() const { + return ComputeTickInterval(timing_function_, scaled_duration(), keyframes_); +} + +std::unique_ptr KeyframedRectAnimationCurve::Clone() const { + std::unique_ptr to_return = + KeyframedRectAnimationCurve::Create(); + for (const auto& keyframe : keyframes_) + to_return->AddKeyframe(keyframe->Clone()); + + if (timing_function_) + to_return->SetTimingFunction(timing_function_->Clone()); + + to_return->set_scaled_duration(scaled_duration()); + + return std::move(to_return); +} + +gfx::Rect KeyframedRectAnimationCurve::GetValue(base::TimeDelta t) const { + if (t <= (keyframes_.front()->Time() * scaled_duration())) + return keyframes_.front()->Value(); + + if (t >= (keyframes_.back()->Time() * scaled_duration())) + return keyframes_.back()->Value(); + + t = TransformedAnimationTime(keyframes_, timing_function_, scaled_duration(), + t); + size_t i = GetActiveKeyframe(keyframes_, scaled_duration(), t); + double progress = + TransformedKeyframeProgress(keyframes_, scaled_duration(), t, i); + + return gfx::Tween::RectValueBetween(progress, keyframes_[i]->Value(), + keyframes_[i + 1]->Value()); +} + } // 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 50bbb3b880f..cf35b9e2d95 100644 --- a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h +++ b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve.h @@ -13,6 +13,7 @@ #include "ui/gfx/animation/keyframe/animation_curve.h" #include "ui/gfx/animation/keyframe/keyframe_animation_export.h" #include "ui/gfx/animation/keyframe/timing_function.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/transform_operations.h" @@ -118,6 +119,26 @@ class GFX_KEYFRAME_ANIMATION_EXPORT SizeKeyframe : public Keyframe { gfx::SizeF value_; }; +class GFX_KEYFRAME_ANIMATION_EXPORT RectKeyframe : public Keyframe { + public: + static std::unique_ptr Create( + base::TimeDelta time, + const gfx::Rect& value, + std::unique_ptr timing_function); + ~RectKeyframe() override; + + const gfx::Rect& Value() const; + + std::unique_ptr Clone() const; + + private: + RectKeyframe(base::TimeDelta time, + const gfx::Rect& value, + std::unique_ptr timing_function); + + gfx::Rect value_; +}; + class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedColorAnimationCurve : public ColorAnimationCurve { public: @@ -287,6 +308,45 @@ class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedSizeAnimationCurve double scaled_duration_; }; +class GFX_KEYFRAME_ANIMATION_EXPORT KeyframedRectAnimationCurve + : public RectAnimationCurve { + public: + // It is required that the keyframes be sorted by time. + static std::unique_ptr Create(); + + KeyframedRectAnimationCurve(const KeyframedRectAnimationCurve&) = delete; + ~KeyframedRectAnimationCurve() override; + + KeyframedRectAnimationCurve& operator=(const KeyframedRectAnimationCurve&) = + delete; + + void AddKeyframe(std::unique_ptr keyframe); + void SetTimingFunction(std::unique_ptr timing_function) { + timing_function_ = std::move(timing_function); + } + double scaled_duration() const { return scaled_duration_; } + void set_scaled_duration(double scaled_duration) { + scaled_duration_ = scaled_duration; + } + + // AnimationCurve implementation + base::TimeDelta Duration() const override; + std::unique_ptr Clone() const override; + base::TimeDelta TickInterval() const override; + + // RectAnimationCurve implementation + gfx::Rect GetValue(base::TimeDelta t) const override; + + private: + KeyframedRectAnimationCurve(); + + // Always sorted in order of increasing time. No two keyframes have the + // same time. + std::vector> keyframes_; + std::unique_ptr timing_function_; + double scaled_duration_ = 0.; +}; + } // namespace gfx #endif // UI_GFX_ANIMATION_KEYFRAME_KEYFRAMED_ANIMATION_CURVE_H_ diff --git a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve_unittest.cc b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve_unittest.cc index c83350bbf55..0242882c0aa 100644 --- a/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve_unittest.cc +++ b/chromium/ui/gfx/animation/keyframe/keyframed_animation_curve_unittest.cc @@ -916,6 +916,98 @@ TEST(KeyframedAnimationCurveTest, RepeatedSizeKeyFrame) { EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::TimeDelta::FromSecondsD(3.f))); } +// Tests that a rect animation with one keyframe works as expected. +TEST(KeyframedAnimationCurveTest, OneRectKeyFrame) { + gfx::Rect rect = gfx::Rect(1, 2, 101, 102); + std::unique_ptr curve( + KeyframedRectAnimationCurve::Create()); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect, nullptr)); + + EXPECT_EQ(rect, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); + EXPECT_EQ(rect, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); + EXPECT_EQ(rect, curve->GetValue(base::TimeDelta::FromSecondsD(0.5f))); + EXPECT_EQ(rect, curve->GetValue(base::TimeDelta::FromSecondsD(1.f))); + EXPECT_EQ(rect, curve->GetValue(base::TimeDelta::FromSecondsD(2.f))); +} + +// Tests that a rect animation with two keyframes works as expected. +TEST(KeyframedAnimationCurveTest, TwoRectKeyFrame) { + gfx::Rect rect_a = gfx::Rect(1, 2, 100, 100); + gfx::Rect rect_b = gfx::Rect(11, 12, 100, 0); + gfx::Rect rect_midpoint = gfx::Tween::RectValueBetween(0.5, rect_a, rect_b); + std::unique_ptr curve( + KeyframedRectAnimationCurve::Create()); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect_a, nullptr)); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), + rect_b, nullptr)); + + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); + EXPECT_EQ(rect_midpoint, + curve->GetValue(base::TimeDelta::FromSecondsD(0.5f))); + EXPECT_EQ(rect_b, curve->GetValue(base::TimeDelta::FromSecondsD(1.f))); + EXPECT_EQ(rect_b, curve->GetValue(base::TimeDelta::FromSecondsD(2.f))); +} + +// Tests that a rect animation with three keyframes works as expected. +TEST(KeyframedAnimationCurveTest, ThreeRectKeyFrame) { + gfx::Rect rect_a = gfx::Rect(1, 2, 100, 100); + gfx::Rect rect_b = gfx::Rect(11, 12, 100, 0); + gfx::Rect rect_c = gfx::Rect(101, 102, 200, 0); + gfx::Rect rect_midpoint1 = gfx::Tween::RectValueBetween(0.5, rect_a, rect_b); + gfx::Rect rect_midpoint2 = gfx::Tween::RectValueBetween(0.5, rect_b, rect_c); + std::unique_ptr curve( + KeyframedRectAnimationCurve::Create()); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect_a, nullptr)); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), + rect_b, nullptr)); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta::FromSecondsD(2.0), + rect_c, nullptr)); + + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); + EXPECT_EQ(rect_midpoint1, + curve->GetValue(base::TimeDelta::FromSecondsD(0.5f))); + EXPECT_EQ(rect_b, curve->GetValue(base::TimeDelta::FromSecondsD(1.f))); + EXPECT_EQ(rect_midpoint2, + curve->GetValue(base::TimeDelta::FromSecondsD(1.5f))); + EXPECT_EQ(rect_c, curve->GetValue(base::TimeDelta::FromSecondsD(2.f))); + EXPECT_EQ(rect_c, curve->GetValue(base::TimeDelta::FromSecondsD(3.f))); +} + +// Tests that a rect animation with multiple keys at a given time works sanely. +TEST(KeyframedAnimationCurveTest, RepeatedRectKeyFrame) { + gfx::Rect rect_a = gfx::Rect(10, 20, 100, 64); + gfx::Rect rect_b = gfx::Rect(30, 40, 100, 192); + + std::unique_ptr curve( + KeyframedRectAnimationCurve::Create()); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect_a, nullptr)); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), + rect_a, nullptr)); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), + rect_b, nullptr)); + curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta::FromSecondsD(2.0), + rect_b, nullptr)); + + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(-1.f))); + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(0.f))); + EXPECT_EQ(rect_a, curve->GetValue(base::TimeDelta::FromSecondsD(0.5f))); + + gfx::Rect value = curve->GetValue(base::TimeDelta::FromSecondsD(1.0f)); + EXPECT_EQ(100, value.width()); + EXPECT_LE(64, value.height()); + EXPECT_GE(192, value.height()); + EXPECT_LE(10, value.x()); + EXPECT_GE(30, value.x()); + EXPECT_LE(20, value.y()); + EXPECT_GE(40, value.y()); + + EXPECT_EQ(rect_b, curve->GetValue(base::TimeDelta::FromSecondsD(1.5f))); + EXPECT_EQ(rect_b, curve->GetValue(base::TimeDelta::FromSecondsD(2.f))); + EXPECT_EQ(rect_b, curve->GetValue(base::TimeDelta::FromSecondsD(3.f))); +} + // Tests that the computing of tick interval for STEPS TimingFunction works // correctly. TEST(KeyFrameAnimationCurveTest, TickIntervalForStepsTimingFunction) { diff --git a/chromium/ui/gfx/animation/multi_animation.cc b/chromium/ui/gfx/animation/multi_animation.cc index de0be7d78a5..09b4423a3fa 100644 --- a/chromium/ui/gfx/animation/multi_animation.cc +++ b/chromium/ui/gfx/animation/multi_animation.cc @@ -15,7 +15,7 @@ namespace gfx { static base::TimeDelta TotalTime(const MultiAnimation::Parts& parts) { return std::accumulate(parts.cbegin(), parts.cend(), base::TimeDelta(), [](base::TimeDelta total, const auto& part) { - return total + part.part_length; + return total + part.length; }); } @@ -24,41 +24,36 @@ constexpr base::TimeDelta MultiAnimation::kDefaultTimerInterval; MultiAnimation::MultiAnimation(const Parts& parts, base::TimeDelta timer_interval) - : Animation(timer_interval), - parts_(parts), - cycle_time_(TotalTime(parts)), - current_value_(0), - current_part_index_(0), - continuous_(true) { + : Animation(timer_interval), parts_(parts), cycle_time_(TotalTime(parts)) { DCHECK(!parts_.empty()); - for (const auto& part : parts) - DCHECK_GE(part.total_length - part.part_start, part.part_length); } MultiAnimation::~MultiAnimation() = default; double MultiAnimation::GetCurrentValue() const { - return current_value_; + const Part& current_part = parts_[current_part_index_]; + return Tween::DoubleValueBetween( + Tween::CalculateValue(current_part.type, current_part_state_), + current_part.start_value, current_part.end_value); } void MultiAnimation::Step(base::TimeTicks time_now) { - double last_value = current_value_; + double last_value = GetCurrentValue(); size_t last_index = current_part_index_; base::TimeDelta delta = time_now - start_time(); bool should_stop = delta >= cycle_time_ && !continuous_; if (should_stop) { current_part_index_ = parts_.size() - 1; - current_value_ = Tween::CalculateValue(parts_[current_part_index_].type, 1); + current_part_state_ = 1.0; } else { delta %= cycle_time_; const Part& part = GetPart(&delta, ¤t_part_index_); - const double percent = (delta + part.part_start) / part.total_length; - DCHECK_LE(percent, 1); - current_value_ = Tween::CalculateValue(part.type, percent); + current_part_state_ = delta / part.length; + DCHECK_LE(current_part_state_, 1); } - if ((current_value_ != last_value || current_part_index_ != last_index) && + if ((GetCurrentValue() != last_value || current_part_index_ != last_index) && delegate()) { // Run AnimationProgressed() even if the animation will be stopped, so that // the animation runs its final frame. @@ -70,7 +65,7 @@ void MultiAnimation::Step(base::TimeTicks time_now) { void MultiAnimation::SetStartTime(base::TimeTicks start_time) { Animation::SetStartTime(start_time); - current_value_ = 0; + current_part_state_ = 0.0; current_part_index_ = 0; } @@ -79,12 +74,12 @@ const MultiAnimation::Part& MultiAnimation::GetPart(base::TimeDelta* time, DCHECK_LT(*time, cycle_time_); for (size_t i = 0; i < parts_.size(); ++i) { - if (*time < parts_[i].part_length) { + if (*time < parts_[i].length) { *part_index = i; return parts_[i]; } - *time -= parts_[i].part_length; + *time -= parts_[i].length; } NOTREACHED(); return parts_[0]; diff --git a/chromium/ui/gfx/animation/multi_animation.h b/chromium/ui/gfx/animation/multi_animation.h index 8c57808386b..3bb0c83a396 100644 --- a/chromium/ui/gfx/animation/multi_animation.h +++ b/chromium/ui/gfx/animation/multi_animation.h @@ -28,35 +28,42 @@ class ANIMATION_EXPORT MultiAnimation : public Animation { // part_start: the amount of time to offset this part by when calculating the // initial percentage. // total_length: the total length used to calculate the percentange completed. + // start_value: the animation value at the beginning of this part of the + // animation. Defaults to 0. + // end_value: the animation value at the end of this part of the animation. + // Defaults to 1. // // In most cases |part_start| is empty and |total_length| = |part_length|. But // you can adjust the start/total for different effects. For example, to run a // part for 200ms with a % between .25 and .75 use the following three values: // part_length = 200, part_start = 100, total_length = 400. + // + // |start_value| and |end_value| can be used to chain multiple animations into + // a single function. A common use case is a MultiAnimation that consists of + // these parts: 0->1 (fade-in), 1->1 (hold) and 1->0 (fade out). struct Part { - Part() : Part(base::TimeDelta(), Tween::ZERO) {} - Part(base::TimeDelta part_length, Tween::Type type) - : Part(part_length, base::TimeDelta(), part_length, type) {} - Part(base::TimeDelta part_length, - base::TimeDelta part_start, - base::TimeDelta total_length, - Tween::Type type) - : part_length(part_length), - part_start(part_start), - total_length(total_length), - type(type) {} - - base::TimeDelta part_length; - base::TimeDelta part_start; - base::TimeDelta total_length; + Part(base::TimeDelta length, + Tween::Type type, + double start_value = 0.0, + double end_value = 1.0) + : length(length), + type(type), + start_value(start_value), + end_value(end_value) {} + + base::TimeDelta length; Tween::Type type; + double start_value; + double end_value; }; using Parts = std::vector; static constexpr auto kDefaultTimerInterval = base::TimeDelta::FromMilliseconds(20); - MultiAnimation(const Parts& parts, base::TimeDelta timer_interval); + explicit MultiAnimation( + const Parts& parts, + base::TimeDelta timer_interval = kDefaultTimerInterval); ~MultiAnimation() override; // Sets whether the animation continues after it reaches the end. If true, the @@ -87,14 +94,14 @@ class ANIMATION_EXPORT MultiAnimation : public Animation { // Total time of all the parts. const base::TimeDelta cycle_time_; - // Current value for the animation. - double current_value_; + // Animation state for the current part. + double current_part_state_ = 0.0; // Index of the current part. - size_t current_part_index_; + size_t current_part_index_ = 0; // See description above setter. - bool continuous_; + bool continuous_ = true; DISALLOW_COPY_AND_ASSIGN(MultiAnimation); }; diff --git a/chromium/ui/gfx/animation/multi_animation_unittest.cc b/chromium/ui/gfx/animation/multi_animation_unittest.cc index ca833058a61..15da71830a5 100644 --- a/chromium/ui/gfx/animation/multi_animation_unittest.cc +++ b/chromium/ui/gfx/animation/multi_animation_unittest.cc @@ -18,7 +18,7 @@ TEST(MultiAnimationTest, Basic) { parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(100), Tween::EASE_OUT)); - MultiAnimation animation(parts, MultiAnimation::kDefaultTimerInterval); + MultiAnimation animation(parts); AnimationContainerElement* as_element = static_cast(&animation); as_element->SetStartTime(base::TimeTicks()); @@ -40,35 +40,12 @@ TEST(MultiAnimationTest, Basic) { animation.GetCurrentValue()); } -TEST(MultiAnimationTest, DifferingStartAndEnd) { - // Create a MultiAnimation with two parts. - MultiAnimation::Parts parts; - parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(200), - base::TimeDelta::FromMilliseconds(100), - base::TimeDelta::FromMilliseconds(400), - Tween::LINEAR)); - - MultiAnimation animation(parts, MultiAnimation::kDefaultTimerInterval); - AnimationContainerElement* as_element = - static_cast(&animation); - as_element->SetStartTime(base::TimeTicks()); - - // Step to 0. Because the start_time is 100, this should be 100ms into the - // animation - as_element->Step(base::TimeTicks()); - EXPECT_EQ(.25, animation.GetCurrentValue()); - - // Step to 100, which is effectively 200ms into the animation. - as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(100)); - EXPECT_EQ(.5, animation.GetCurrentValue()); -} - // Makes sure multi-animation stops if cycles is false. TEST(MultiAnimationTest, DontCycle) { MultiAnimation::Parts parts; parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(200), Tween::LINEAR)); - MultiAnimation animation(parts, MultiAnimation::kDefaultTimerInterval); + MultiAnimation animation(parts); AnimationContainerElement* as_element = static_cast(&animation); as_element->SetStartTime(base::TimeTicks()); @@ -101,7 +78,7 @@ TEST(MultiAnimationTest, ExceedCycleNonContinuous) { MultiAnimation::Parts parts; parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(200), Tween::LINEAR)); - MultiAnimation animation(parts, MultiAnimation::kDefaultTimerInterval); + MultiAnimation animation(parts); CurrentValueDelegate delegate; animation.set_delegate(&delegate); animation.set_continuous(false); @@ -119,7 +96,7 @@ TEST(MultiAnimationTest, Cycle) { MultiAnimation::Parts parts; parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(200), Tween::LINEAR)); - MultiAnimation animation(parts, MultiAnimation::kDefaultTimerInterval); + MultiAnimation animation(parts); AnimationContainerElement* as_element = static_cast(&animation); as_element->SetStartTime(base::TimeTicks()); @@ -129,4 +106,38 @@ TEST(MultiAnimationTest, Cycle) { EXPECT_EQ(.5, animation.GetCurrentValue()); } +// Make sure MultiAnimation::GetCurrentValue is derived from the start and end +// of the current MultiAnimation::Part. +TEST(MultiAnimationTest, GetCurrentValueDerivedFromStartAndEndOfCurrentPart) { + // Create a MultiAnimation with two parts. The second part goes from 0.8 to + // 0.4 instead of the default 0 -> 1. + constexpr double kSecondPartStart = 0.8; + constexpr double kSecondPartEnd = 0.4; + MultiAnimation::Parts parts; + parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(100), + Tween::LINEAR)); + parts.push_back(MultiAnimation::Part(base::TimeDelta::FromMilliseconds(100), + Tween::EASE_OUT, kSecondPartStart, + kSecondPartEnd)); + + MultiAnimation animation(parts); + animation.set_continuous(false); + AnimationContainerElement* as_element = + static_cast(&animation); + as_element->SetStartTime(base::TimeTicks()); + + // Step to 150, which is half way through the second part. + as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(150)); + const double current_animation_value = + Tween::CalculateValue(Tween::EASE_OUT, .5); + EXPECT_DOUBLE_EQ(Tween::DoubleValueBetween(current_animation_value, + kSecondPartStart, kSecondPartEnd), + animation.GetCurrentValue()); + + // Step to 200 which is at the end. The final value should now be kPartEnd as + // the animation is not continuous. + as_element->Step(base::TimeTicks() + base::TimeDelta::FromMilliseconds(200)); + EXPECT_DOUBLE_EQ(kSecondPartEnd, animation.GetCurrentValue()); +} + } // namespace gfx diff --git a/chromium/ui/gfx/animation/tween.cc b/chromium/ui/gfx/animation/tween.cc index 6b9e9dec555..ade58e8acb6 100644 --- a/chromium/ui/gfx/animation/tween.cc +++ b/chromium/ui/gfx/animation/tween.cc @@ -84,6 +84,9 @@ double Tween::CalculateValue(Tween::Type type, double state) { case ACCEL_LIN_DECEL_60: return gfx::CubicBezier(0, 0, 0.4, 1).Solve(state); + case ACCEL_LIN_DECEL_100: + return gfx::CubicBezier(0, 0, 0, 1).Solve(state); + case ACCEL_20_DECEL_60: return gfx::CubicBezier(0.2, 0, 0.4, 1).Solve(state); } diff --git a/chromium/ui/gfx/animation/tween.h b/chromium/ui/gfx/animation/tween.h index e2502a3c202..c2daf2eefd3 100644 --- a/chromium/ui/gfx/animation/tween.h +++ b/chromium/ui/gfx/animation/tween.h @@ -63,8 +63,10 @@ class ANIMATION_EXPORT Tween { // ACCEL_100_DECEL_100 = (1, 0, 0, 1): https://cubic-bezier.com/#1,0,0,1 // ACCEL_LIN_DECEL_LIN = (0, 0, 1, 1): https://cubic-bezier.com/#0,0,1,1 // ACCEL_40_DECEL_80 = (0.4, 0, 0.2, 1): https://cubic-bezier.com/#.4,0,.2,1 - ACCEL_LIN_DECEL_60, // Pulling a small to medium element into a place. - ACCEL_20_DECEL_60, // Moving a small, low emphasis or responsive elements. + ACCEL_LIN_DECEL_60, // Pulling a small to medium element into a place. + ACCEL_LIN_DECEL_100, // Pulling a small to medium element into a place that + // has very fast deceleration. + ACCEL_20_DECEL_60, // Moving a small, low emphasis or responsive elements. }; // Returns the value based on the tween type. |state| is from 0-1. diff --git a/chromium/ui/gfx/bidi_line_iterator.cc b/chromium/ui/gfx/bidi_line_iterator.cc index 0ffb94b5c6f..cda076ac74f 100644 --- a/chromium/ui/gfx/bidi_line_iterator.cc +++ b/chromium/ui/gfx/bidi_line_iterator.cc @@ -5,7 +5,6 @@ #include "ui/gfx/bidi_line_iterator.h" #include "base/check.h" -#include "base/i18n/uchar.h" #include "base/notreached.h" namespace ui { @@ -38,7 +37,7 @@ BiDiLineIterator::~BiDiLineIterator() { } } -bool BiDiLineIterator::Open(const base::string16& text, +bool BiDiLineIterator::Open(const std::u16string& text, base::i18n::TextDirection direction) { DCHECK(!bidi_); UErrorCode error = U_ZERO_ERROR; @@ -46,8 +45,7 @@ bool BiDiLineIterator::Open(const base::string16& text, if (U_FAILURE(error)) return false; - ubidi_setPara(bidi_, base::i18n::ToUCharPtr(text.data()), - static_cast(text.length()), + ubidi_setPara(bidi_, text.data(), static_cast(text.length()), GetParagraphLevelForDirection(direction), nullptr, &error); return (U_SUCCESS(error)); } diff --git a/chromium/ui/gfx/bidi_line_iterator.h b/chromium/ui/gfx/bidi_line_iterator.h index b83be71287f..4e7fd075cac 100644 --- a/chromium/ui/gfx/bidi_line_iterator.h +++ b/chromium/ui/gfx/bidi_line_iterator.h @@ -5,9 +5,10 @@ #ifndef UI_GFX_BIDI_LINE_ITERATOR_H_ #define UI_GFX_BIDI_LINE_ITERATOR_H_ +#include + #include "base/i18n/rtl.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "third_party/icu/source/common/unicode/ubidi.h" #include "third_party/icu/source/common/unicode/uchar.h" #include "ui/gfx/gfx_export.h" @@ -25,7 +26,7 @@ class GFX_EXPORT BiDiLineIterator { // Initializes the bidirectional iterator with the specified text. Returns // whether initialization succeeded. - bool Open(const base::string16& text, base::i18n::TextDirection direction); + bool Open(const std::u16string& text, base::i18n::TextDirection direction); // Returns the number of visual runs in the text, or zero on error. int CountRuns() const; diff --git a/chromium/ui/gfx/bidi_line_iterator_unittest.cc b/chromium/ui/gfx/bidi_line_iterator_unittest.cc index 7f8f58b03cf..d8dbc51cfd6 100644 --- a/chromium/ui/gfx/bidi_line_iterator_unittest.cc +++ b/chromium/ui/gfx/bidi_line_iterator_unittest.cc @@ -26,7 +26,7 @@ class BiDiLineIteratorTest }; TEST_P(BiDiLineIteratorTest, OnlyLTR) { - iterator()->Open(base::UTF8ToUTF16("abc 😁 测试"), GetParam()); + iterator()->Open(u"abc 😁 测试", GetParam()); ASSERT_EQ(1, iterator()->CountRuns()); int start, length; @@ -45,7 +45,7 @@ TEST_P(BiDiLineIteratorTest, OnlyLTR) { } TEST_P(BiDiLineIteratorTest, OnlyRTL) { - iterator()->Open(base::UTF8ToUTF16("מה השעה"), GetParam()); + iterator()->Open(u"מה השעה", GetParam()); ASSERT_EQ(1, iterator()->CountRuns()); int start, length; @@ -61,8 +61,7 @@ TEST_P(BiDiLineIteratorTest, OnlyRTL) { } TEST_P(BiDiLineIteratorTest, Mixed) { - iterator()->Open(base::UTF8ToUTF16("אני משתמש ב- Chrome כדפדפן האינטרנט שלי"), - GetParam()); + iterator()->Open(u"אני משתמש ב- Chrome כדפדפן האינטרנט שלי", GetParam()); ASSERT_EQ(3, iterator()->CountRuns()); // We'll get completely different results depending on the top-level paragraph diff --git a/chromium/ui/gfx/buffer_types.h b/chromium/ui/gfx/buffer_types.h index fbb58c7a668..fc7e33dcb25 100644 --- a/chromium/ui/gfx/buffer_types.h +++ b/chromium/ui/gfx/buffer_types.h @@ -52,6 +52,7 @@ enum class BufferUsage { PROTECTED_SCANOUT_VDA_WRITE, GPU_READ_CPU_READ_WRITE, SCANOUT_VEA_CPU_READ, + SCANOUT_FRONT_RENDERING, VEA_READ_CAMERA_AND_CPU_READ_WRITE, LAST = VEA_READ_CAMERA_AND_CPU_READ_WRITE diff --git a/chromium/ui/gfx/buffer_usage_util.cc b/chromium/ui/gfx/buffer_usage_util.cc index 081cda9b158..d2a66f6aaaf 100644 --- a/chromium/ui/gfx/buffer_usage_util.cc +++ b/chromium/ui/gfx/buffer_usage_util.cc @@ -28,6 +28,8 @@ const char* BufferUsageToString(BufferUsage usage) { return "SCANOUT_VEA_CPU_READ"; case BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE: return "VEA_READ_CAMERA_AND_CPU_READ_WRITE"; + case BufferUsage::SCANOUT_FRONT_RENDERING: + return "SCANOUT_FRONT_RENDERING"; } return "Invalid Usage"; } diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc index 5e60708161c..0f3e5df81a6 100644 --- a/chromium/ui/gfx/canvas.cc +++ b/chromium/ui/gfx/canvas.cc @@ -63,7 +63,7 @@ void Canvas::RecreateBackingCanvas(const Size& size, } // static -void Canvas::SizeStringInt(const base::string16& text, +void Canvas::SizeStringInt(const std::u16string& text, const FontList& font_list, int* width, int* height, @@ -78,7 +78,7 @@ void Canvas::SizeStringInt(const base::string16& text, } // static -int Canvas::GetStringWidth(const base::string16& text, +int Canvas::GetStringWidth(const std::u16string& text, const FontList& font_list) { int width = 0, height = 0; SizeStringInt(text, font_list, &width, &height, 0, NO_ELLIPSIS); @@ -86,7 +86,7 @@ int Canvas::GetStringWidth(const base::string16& text, } // static -float Canvas::GetStringWidthF(const base::string16& text, +float Canvas::GetStringWidthF(const std::u16string& text, const FontList& font_list) { float width = 0, height = 0; SizeStringFloat(text, font_list, &width, &height, 0, NO_ELLIPSIS); @@ -397,7 +397,7 @@ void Canvas::DrawSkottie(scoped_refptr skottie, canvas_->drawSkottie(std::move(skottie), RectToSkRect(dst), t); } -void Canvas::DrawStringRect(const base::string16& text, +void Canvas::DrawStringRect(const std::u16string& text, const FontList& font_list, SkColor color, const Rect& display_rect) { diff --git a/chromium/ui/gfx/canvas.h b/chromium/ui/gfx/canvas.h index abad2e6ce7b..16acd944ad4 100644 --- a/chromium/ui/gfx/canvas.h +++ b/chromium/ui/gfx/canvas.h @@ -8,11 +8,11 @@ #include #include +#include #include #include "base/macros.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "cc/paint/skia_paint_canvas.h" @@ -113,7 +113,7 @@ class GFX_EXPORT Canvas { // height and then width as needed to make the text fit. This method // supports multiple lines. On Skia only a line_height can be specified and // specifying a 0 value for it will cause the default height to be used. - static void SizeStringInt(const base::string16& text, + static void SizeStringInt(const std::u16string& text, const FontList& font_list, int* width, int* height, @@ -122,7 +122,7 @@ class GFX_EXPORT Canvas { // This is same as SizeStringInt except that fractional size is returned. // See comment in GetStringWidthF for its usage. - static void SizeStringFloat(const base::string16& text, + static void SizeStringFloat(const std::u16string& text, const FontList& font_list, float* width, float* height, @@ -131,7 +131,7 @@ class GFX_EXPORT Canvas { // Returns the number of horizontal pixels needed to display the specified // |text| with |font_list|. - static int GetStringWidth(const base::string16& text, + static int GetStringWidth(const std::u16string& text, const FontList& font_list); // This is same as GetStringWidth except that fractional width is returned. @@ -139,7 +139,7 @@ class GFX_EXPORT Canvas { // summed up. This is because GetStringWidth returns the ceiled width and // adding multiple ceiled widths could cause more precision loss for certain // platform like Mac where the fractional width is used. - static float GetStringWidthF(const base::string16& text, + static float GetStringWidthF(const std::u16string& text, const FontList& font_list); // Returns the default text alignment to be used when drawing text on a @@ -364,7 +364,7 @@ class GFX_EXPORT Canvas { // Draws text with the specified color, fonts and location. The text is // aligned to the left, vertically centered, clipped to the region. If the // text is too big, it is truncated and '...' is added to the end. - void DrawStringRect(const base::string16& text, + void DrawStringRect(const std::u16string& text, const FontList& font_list, SkColor color, const Rect& display_rect); @@ -372,7 +372,7 @@ class GFX_EXPORT Canvas { // Draws text with the specified color, fonts and location. The last argument // specifies flags for how the text should be rendered. It can be one of // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT. - void DrawStringRectWithFlags(const base::string16& text, + void DrawStringRectWithFlags(const std::u16string& text, const FontList& font_list, SkColor color, const Rect& display_rect, diff --git a/chromium/ui/gfx/canvas_skia.cc b/chromium/ui/gfx/canvas_skia.cc index 4ef6a0660d0..5ebc4a1a96d 100644 --- a/chromium/ui/gfx/canvas_skia.cc +++ b/chromium/ui/gfx/canvas_skia.cc @@ -24,7 +24,7 @@ namespace { // Strips accelerator character prefixes in |text| if needed, based on |flags|. // Returns a range in |text| to underline or Range::InvalidRange() if // underlining is not needed. -Range StripAcceleratorChars(int flags, base::string16* text) { +Range StripAcceleratorChars(int flags, std::u16string* text) { if (flags & Canvas::SHOW_PREFIX) { int char_pos = -1; int char_span = 0; @@ -42,10 +42,10 @@ Range StripAcceleratorChars(int flags, base::string16* text) { // to no longer point to the same character in |text|, |range| is made invalid. void ElideTextAndAdjustRange(const FontList& font_list, float width, - base::string16* text, + std::u16string* text, Range* range) { - const base::char16 start_char = - (range->IsValid() ? text->at(range->start()) : 0); + const char16_t start_char = + (range->IsValid() ? text->at(range->start()) : u'\0'); *text = ElideText(*text, font_list, width, ELIDE_TAIL); if (!range->IsValid()) return; @@ -57,7 +57,7 @@ void ElideTextAndAdjustRange(const FontList& font_list, // Updates |render_text| from the specified parameters. void UpdateRenderText(const Rect& rect, - const base::string16& text, + const std::u16string& text, const FontList& font_list, int flags, SkColor color, @@ -99,7 +99,7 @@ void UpdateRenderText(const Rect& rect, } // namespace // static -void Canvas::SizeStringFloat(const base::string16& text, +void Canvas::SizeStringFloat(const std::u16string& text, const FontList& font_list, float* width, float* height, @@ -115,14 +115,14 @@ void Canvas::SizeStringFloat(const base::string16& text, else if (!(flags & NO_ELLIPSIS)) wrap_behavior = ELIDE_LONG_WORDS; - std::vector strings; + std::vector strings; ElideRectangleText(text, font_list, *width, INT_MAX, wrap_behavior, &strings); Rect rect(base::saturated_cast(*width), INT_MAX); std::unique_ptr render_text = RenderText::CreateRenderText(); - UpdateRenderText(rect, base::string16(), font_list, flags, 0, + UpdateRenderText(rect, std::u16string(), font_list, flags, 0, render_text.get()); float h = 0; @@ -143,7 +143,7 @@ void Canvas::SizeStringFloat(const base::string16& text, Rect rect(base::saturated_cast(*width), base::saturated_cast(*height)); - base::string16 adjusted_text = text; + std::u16string adjusted_text = text; StripAcceleratorChars(flags, &adjusted_text); UpdateRenderText(rect, adjusted_text, font_list, flags, 0, render_text.get()); @@ -153,7 +153,7 @@ void Canvas::SizeStringFloat(const base::string16& text, } } -void Canvas::DrawStringRectWithFlags(const base::string16& text, +void Canvas::DrawStringRectWithFlags(const std::u16string& text, const FontList& font_list, SkColor color, const Rect& text_bounds, @@ -175,7 +175,7 @@ void Canvas::DrawStringRectWithFlags(const base::string16& text, else if (!(flags & NO_ELLIPSIS)) wrap_behavior = ELIDE_LONG_WORDS; - std::vector strings; + std::vector strings; ElideRectangleText(text, font_list, static_cast(text_bounds.width()), text_bounds.height(), wrap_behavior, &strings); @@ -205,7 +205,7 @@ void Canvas::DrawStringRectWithFlags(const base::string16& text, rect += Vector2d(0, line_height); } } else { - base::string16 adjusted_text = text; + std::u16string adjusted_text = text; Range range = StripAcceleratorChars(flags, &adjusted_text); bool elide_text = ((flags & NO_ELLIPSIS) == 0); diff --git a/chromium/ui/gfx/canvas_unittest.cc b/chromium/ui/gfx/canvas_unittest.cc index 6b1dae948e5..6f985624293 100644 --- a/chromium/ui/gfx/canvas_unittest.cc +++ b/chromium/ui/gfx/canvas_unittest.cc @@ -23,10 +23,10 @@ class CanvasTest : public testing::Test { } gfx::Size SizeStringInt(const char *text, int width, int line_height) { - base::string16 text16 = base::UTF8ToUTF16(text); + std::u16string text16 = base::UTF8ToUTF16(text); int height = 0; int flags = - (text16.find('\n') != base::string16::npos) ? Canvas::MULTI_LINE : 0; + (text16.find('\n') != std::u16string::npos) ? Canvas::MULTI_LINE : 0; Canvas::SizeStringInt(text16, font_list_, &width, &height, line_height, flags); return gfx::Size(width, height); diff --git a/chromium/ui/gfx/color_palette.h b/chromium/ui/gfx/color_palette.h index 8cdcba3187c..ebf2cdedc55 100644 --- a/chromium/ui/gfx/color_palette.h +++ b/chromium/ui/gfx/color_palette.h @@ -60,7 +60,7 @@ constexpr SkColor kGoogleGreenDark600 = SkColorSetRGB(0x28, 0x99, 0x4F); constexpr SkColor kGoogleYellow050 = SkColorSetRGB(0xFE, 0xF7, 0xE0); constexpr SkColor kGoogleYellow100 = SkColorSetRGB(0xFE, 0xEF, 0xC3); -constexpr SkColor kGoogleYellow200 = SkColorSetRGB(0xFB, 0xBC, 0x04); +constexpr SkColor kGoogleYellow200 = SkColorSetRGB(0xFD, 0xE2, 0x93); constexpr SkColor kGoogleYellow300 = SkColorSetRGB(0xFD, 0xD6, 0x63); constexpr SkColor kGoogleYellow400 = SkColorSetRGB(0xFC, 0xC9, 0x34); constexpr SkColor kGoogleYellow500 = SkColorSetRGB(0xFB, 0xBC, 0x04); diff --git a/chromium/ui/gfx/color_transform_unittest.cc b/chromium/ui/gfx/color_transform_unittest.cc index 1b91fc4e566..f576087850e 100644 --- a/chromium/ui/gfx/color_transform_unittest.cc +++ b/chromium/ui/gfx/color_transform_unittest.cc @@ -562,7 +562,7 @@ TEST(SimpleColorSpace, CanParseSkShaderSource) { auto transform = ColorTransform::NewColorTransform( src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL); std::string source = - "in shader child;\n" + "uniform shader child;\n" "half4 main() {\n" " half4 color = sample(child);\n" + transform->GetSkShaderSource() + " return color; }"; diff --git a/chromium/ui/gfx/decorated_text.h b/chromium/ui/gfx/decorated_text.h index d1611523ebd..9d53d054755 100644 --- a/chromium/ui/gfx/decorated_text.h +++ b/chromium/ui/gfx/decorated_text.h @@ -5,9 +5,9 @@ #ifndef UI_GFX_DECORATED_TEXT_H_ #define UI_GFX_DECORATED_TEXT_H_ +#include #include -#include "base/strings/string16.h" #include "ui/gfx/font.h" #include "ui/gfx/gfx_export.h" #include "ui/gfx/range/range.h" @@ -33,7 +33,7 @@ struct GFX_EXPORT DecoratedText { DecoratedText(); ~DecoratedText(); - base::string16 text; + std::u16string text; // Vector of RangedAttribute describing styling of non-overlapping ranges // in |text|. diff --git a/chromium/ui/gfx/delegated_ink_metadata.cc b/chromium/ui/gfx/delegated_ink_metadata.cc new file mode 100644 index 00000000000..eea84b1e379 --- /dev/null +++ b/chromium/ui/gfx/delegated_ink_metadata.cc @@ -0,0 +1,24 @@ +// 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/gfx/delegated_ink_metadata.h" + +#include + +#include "base/strings/stringprintf.h" + +namespace gfx { + +std::string DelegatedInkMetadata::ToString() const { + std::string str = base::StringPrintf( + "point: %s, diameter: %f, color: %u, timestamp: %" PRId64 + ", presentation_area: %s, frame_time: %" PRId64 ", is_hovering: %d", + point_.ToString().c_str(), diameter_, color_, + timestamp_.since_origin().InMicroseconds(), + presentation_area_.ToString().c_str(), + frame_time_.since_origin().InMicroseconds(), is_hovering_); + return str; +} + +} // namespace gfx diff --git a/chromium/ui/gfx/delegated_ink_metadata.h b/chromium/ui/gfx/delegated_ink_metadata.h new file mode 100644 index 00000000000..a1103157740 --- /dev/null +++ b/chromium/ui/gfx/delegated_ink_metadata.h @@ -0,0 +1,94 @@ +// 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_GFX_DELEGATED_INK_METADATA_H_ +#define UI_GFX_DELEGATED_INK_METADATA_H_ + +#include + +#include "base/time/time.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/gfx_export.h" + +namespace gfx { + +// This class stores all the metadata that is gathered when the WebAPI +// updateInkTrailStartPoint is called. This metadata flows from blink, +// through cc, and into viz in order to produce a delegated ink trail on the +// end of what was already rendered. +// +// Explainer for the feature: +// https://github.com/WICG/ink-enhancement/blob/master/README.md +class GFX_EXPORT DelegatedInkMetadata { + public: + DelegatedInkMetadata() = default; + DelegatedInkMetadata(const PointF& pt, + double diameter, + SkColor color, + base::TimeTicks timestamp, + const RectF& area, + bool hovering) + : point_(pt), + diameter_(diameter), + color_(color), + timestamp_(timestamp), + presentation_area_(area), + is_hovering_(hovering) {} + DelegatedInkMetadata(const PointF& pt, + double diameter, + SkColor color, + base::TimeTicks timestamp, + const RectF& area, + base::TimeTicks frame_time, + bool hovering) + : point_(pt), + diameter_(diameter), + color_(color), + timestamp_(timestamp), + presentation_area_(area), + frame_time_(frame_time), + is_hovering_(hovering) {} + DelegatedInkMetadata(const DelegatedInkMetadata& other) = default; + + const PointF& point() const { return point_; } + double diameter() const { return diameter_; } + SkColor color() const { return color_; } + base::TimeTicks timestamp() const { return timestamp_; } + const RectF& presentation_area() const { return presentation_area_; } + base::TimeTicks frame_time() const { return frame_time_; } + bool is_hovering() const { return is_hovering_; } + + void set_frame_time(base::TimeTicks frame_time) { frame_time_ = frame_time; } + + std::string ToString() const; + + private: + // Location of the pointerevent relative to the root frame. + PointF point_; + + // Width of the trail, in physical pixels. + double diameter_ = 0; + + // Color to draw the ink trail. + SkColor color_ = 0; + + // Timestamp from the pointerevent for the ink point. + base::TimeTicks timestamp_; + + // The rect to clip the ink trail to, defaults to the containing viewport. + RectF presentation_area_; + + // Frame time of the layer tree that this metadata is on. + base::TimeTicks frame_time_; + + // True if the left mouse button is up or if a stylus with hovering + // capabilities is hovering over the screen when updateInkTrailStartPoint is + // called. + bool is_hovering_ = false; +}; + +} // namespace gfx + +#endif // UI_GFX_DELEGATED_INK_METADATA_H_ diff --git a/chromium/ui/gfx/delegated_ink_point.cc b/chromium/ui/gfx/delegated_ink_point.cc new file mode 100644 index 00000000000..8648d30f486 --- /dev/null +++ b/chromium/ui/gfx/delegated_ink_point.cc @@ -0,0 +1,20 @@ +// 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/gfx/delegated_ink_point.h" + +#include + +#include "base/strings/stringprintf.h" + +namespace gfx { + +std::string DelegatedInkPoint::ToString() const { + return base::StringPrintf("point: %s, timestamp: %" PRId64 ", pointer_id: %d", + point_.ToString().c_str(), + timestamp_.since_origin().InMicroseconds(), + pointer_id_); +} + +} // namespace gfx diff --git a/chromium/ui/gfx/delegated_ink_point.h b/chromium/ui/gfx/delegated_ink_point.h new file mode 100644 index 00000000000..ec46f369da5 --- /dev/null +++ b/chromium/ui/gfx/delegated_ink_point.h @@ -0,0 +1,64 @@ +// 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_GFX_DELEGATED_INK_POINT_H_ +#define UI_GFX_DELEGATED_INK_POINT_H_ + +#include + +#include "base/time/time.h" +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/gfx_export.h" + +namespace gfx { + +namespace mojom { +class DelegatedInkPointDataView; +} // namespace mojom + +// This class stores the information required to draw a single point of a +// delegated ink trail. When the WebAPI |updateInkTrailStartPoint| is called, +// the renderer requests that the browser begin sending these to viz. Viz +// will collect them, and then during |DrawAndSwap| will use the +// DelegatedInkPoints that have arrived from the browser along with the +// DelegatedInkMetadata that the renderer sent to draw a delegated ink trail on +// the screen, connected to the end of the already rendered ink stroke. +// +// Explainer for the feature: +// https://github.com/WICG/ink-enhancement/blob/master/README.md +class GFX_EXPORT DelegatedInkPoint { + public: + DelegatedInkPoint() = default; + DelegatedInkPoint(const PointF& pt, + base::TimeTicks timestamp, + int32_t pointer_id) + : point_(pt), timestamp_(timestamp), pointer_id_(pointer_id) {} + + const PointF& point() const { return point_; } + base::TimeTicks timestamp() const { return timestamp_; } + int32_t pointer_id() const { return pointer_id_; } + std::string ToString() const; + + private: + friend struct mojo::StructTraits; + + // Location of the input event relative to the root window in device pixels. + // Scale is device scale factor at time of input. + PointF point_; + + // Timestamp from the input event. + base::TimeTicks timestamp_; + + // Pointer ID from the input event. Used to store all DelegatedInkPoints from + // the same source together in viz so that they are all candidates for a + // single delegated ink trail and DelegatedInkPoints from other sources are + // not. + int32_t pointer_id_; +}; + +} // namespace gfx + +#endif // UI_GFX_DELEGATED_INK_POINT_H_ diff --git a/chromium/ui/gfx/font.h b/chromium/ui/gfx/font.h index f8aa02af51c..f797b0d87b3 100644 --- a/chromium/ui/gfx/font.h +++ b/chromium/ui/gfx/font.h @@ -8,7 +8,6 @@ #include #include "base/memory/ref_counted.h" -#include "base/strings/string16.h" #include "build/build_config.h" #include "ui/gfx/gfx_export.h" #include "ui/gfx/native_widget_types.h" diff --git a/chromium/ui/gfx/font_fallback.h b/chromium/ui/gfx/font_fallback.h index 6b21e3273e0..001ec40eb98 100644 --- a/chromium/ui/gfx/font_fallback.h +++ b/chromium/ui/gfx/font_fallback.h @@ -5,9 +5,9 @@ #ifndef UI_GFX_FONT_FALLBACK_H_ #define UI_GFX_FONT_FALLBACK_H_ +#include #include -#include "base/strings/string16.h" #include "build/build_config.h" #include "ui/gfx/font.h" #include "ui/gfx/gfx_export.h" diff --git a/chromium/ui/gfx/font_fallback_linux_unittest.cc b/chromium/ui/gfx/font_fallback_linux_unittest.cc index a7c582d9499..ec156cfc9f7 100644 --- a/chromium/ui/gfx/font_fallback_linux_unittest.cc +++ b/chromium/ui/gfx/font_fallback_linux_unittest.cc @@ -41,13 +41,13 @@ TEST_F(FontFallbackLinuxTest, GetFallbackFont) { Font base_font; Font fallback_font_cjk; - EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, - base::WideToUTF16(L"⻩"), &fallback_font_cjk)); + EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, u"⻩", + &fallback_font_cjk)); EXPECT_EQ(fallback_font_cjk.GetFontName(), "Noto Sans CJK JP"); Font fallback_font_khmer; - EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, - base::WideToUTF16(L"ឨឮឡ"), &fallback_font_khmer)); + EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, u"ឨឮឡ", + &fallback_font_khmer)); EXPECT_EQ(fallback_font_khmer.GetFontName(), "Noto Sans Khmer"); } @@ -56,24 +56,24 @@ TEST_F(FontFallbackLinuxTest, GetFallbackFontCache) { Font base_font; Font fallback_font; - EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, - base::WideToUTF16(L"⻩"), &fallback_font)); + EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, u"⻩", + &fallback_font)); EXPECT_EQ(1U, GetFallbackFontEntriesCacheSizeForTesting()); // Second call should not increase the cache size. - EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, - base::WideToUTF16(L"⻩"), &fallback_font)); + EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, u"⻩", + &fallback_font)); EXPECT_EQ(1U, GetFallbackFontEntriesCacheSizeForTesting()); // Third call with a different code point in the same font, should not // increase the cache size. - EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, - base::WideToUTF16(L"⻪"), &fallback_font)); + EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, u"⻪", + &fallback_font)); EXPECT_EQ(1U, GetFallbackFontEntriesCacheSizeForTesting()); // A different locale should trigger an new cache entry. - EXPECT_TRUE(GetFallbackFont(base_font, kFrenchApplicationLocale, - base::WideToUTF16(L"⻩"), &fallback_font)); + EXPECT_TRUE(GetFallbackFont(base_font, kFrenchApplicationLocale, u"⻩", + &fallback_font)); EXPECT_EQ(2U, GetFallbackFontEntriesCacheSizeForTesting()); // The fallbackfonts cache should not be affected. diff --git a/chromium/ui/gfx/font_fallback_mac_unittest.cc b/chromium/ui/gfx/font_fallback_mac_unittest.cc index aaca9deadc1..dbb1724194a 100644 --- a/chromium/ui/gfx/font_fallback_mac_unittest.cc +++ b/chromium/ui/gfx/font_fallback_mac_unittest.cc @@ -30,9 +30,9 @@ TEST(FontFallbackMacTest, GetFallbackFonts) { // about font properties and availability on specific macOS versions. TEST(FontFallbackMacTest, GetFallbackFont) { Font arial("Helvetica", 12); - const base::string16 ascii = base::ASCIIToUTF16("abc"); - const base::string16 hebrew = base::WideToUTF16(L"\x5d0\x5d1\x5d2"); - const base::string16 emoji = base::UTF8ToUTF16("😋"); + const std::u16string ascii = u"abc"; + const std::u16string hebrew = u"\x5d0\x5d1\x5d2"; + const std::u16string emoji = u"😋"; Font fallback; EXPECT_TRUE( diff --git a/chromium/ui/gfx/font_fallback_skia_unittest.cc b/chromium/ui/gfx/font_fallback_skia_unittest.cc index e700c714736..01bd3f255ce 100644 --- a/chromium/ui/gfx/font_fallback_skia_unittest.cc +++ b/chromium/ui/gfx/font_fallback_skia_unittest.cc @@ -36,7 +36,7 @@ TEST(FontFallbackSkiaTest, FontFallback) { for (const auto* test : kFallbackFontTests) { Font base_font; Font fallback_font; - base::string16 text = base::WideToUTF16(test); + std::u16string text = base::WideToUTF16(test); if (!GetFallbackFont(base_font, kDefaultApplicationLocale, text, &fallback_font)) { @@ -55,7 +55,7 @@ TEST(FontFallbackSkiaTest, CJKLocaleFallback) { // common feature of written Chinese (hanzi), Japanese (kanji), and Korean // (hanja). The same text will be rendered using a different font based on // locale. - const base::string16 kCJKTest = base::WideToUTF16(L"\u8AA4\u904E\u9AA8"); + const std::u16string kCJKTest = u"\u8AA4\u904E\u9AA8"; Font base_font; Font fallback_font_zh_cn; diff --git a/chromium/ui/gfx/font_fallback_unittest.cc b/chromium/ui/gfx/font_fallback_unittest.cc index 3af544bf66b..46736424ad6 100644 --- a/chromium/ui/gfx/font_fallback_unittest.cc +++ b/chromium/ui/gfx/font_fallback_unittest.cc @@ -6,7 +6,6 @@ #include -#include "base/i18n/uchar.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -91,7 +90,7 @@ class GetFallbackFontTest return gfx::GetFallbackFont(font, language_tag, test_case_.text, result); } - bool EnsuresScriptSupportCodePoints(const base::string16& text, + bool EnsuresScriptSupportCodePoints(const std::u16string& text, UScriptCode script, const std::string& script_name) { size_t i = 0; @@ -114,7 +113,7 @@ class GetFallbackFontTest return true; } - bool DoesFontSupportCodePoints(Font font, const base::string16& text) { + bool DoesFontSupportCodePoints(Font font, const std::u16string& text) { sk_sp skia_face = font.platform_font()->GetNativeSkTypeface(); if (!skia_face) { ADD_FAILURE() << "Cannot create typeface for '" << font.GetFontName() @@ -236,10 +235,10 @@ std::vector GetSampleFontTestCases() { const UScriptCode script = static_cast(i); // Make a sample text to test the script. - base::char16 text[8]; + char16_t text[8]; UErrorCode errorCode = U_ZERO_ERROR; - int text_length = uscript_getSampleString( - script, base::i18n::ToUCharPtr(text), base::size(text), &errorCode); + int text_length = + uscript_getSampleString(script, text, base::size(text), &errorCode); if (text_length <= 0 || errorCode != U_ZERO_ERROR) continue; diff --git a/chromium/ui/gfx/font_fallback_win.cc b/chromium/ui/gfx/font_fallback_win.cc index 0f7253bf35e..b07343805a0 100644 --- a/chromium/ui/gfx/font_fallback_win.cc +++ b/chromium/ui/gfx/font_fallback_win.cc @@ -57,7 +57,7 @@ void GetFontNamesFromFilename(const std::string& filename, // Returns true if |text| contains only ASCII digits. bool ContainsOnlyDigits(const std::string& text) { - return text.find_first_not_of("0123456789") == base::string16::npos; + return text.find_first_not_of("0123456789") == std::u16string::npos; } // Appends a Font with the given |name| and |size| to |fonts| unless the last @@ -224,7 +224,7 @@ bool GetFallbackFont(const Font& font, // Check that we have at least as much text as was claimed. If we have less // text than expected then DirectWrite will become confused and crash. This // shouldn't happen, but crbug.com/624905 shows that it happens sometimes. - constexpr base::char16 kNulCharacter = '\0'; + constexpr char16_t kNulCharacter = '\0'; if (text.find(kNulCharacter) != base::StringPiece16::npos) return false; diff --git a/chromium/ui/gfx/font_fallback_win_unittest.cc b/chromium/ui/gfx/font_fallback_win_unittest.cc index a1b05ae1abd..d73a354958f 100644 --- a/chromium/ui/gfx/font_fallback_win_unittest.cc +++ b/chromium/ui/gfx/font_fallback_win_unittest.cc @@ -88,18 +88,18 @@ TEST_F(FontFallbackWinTest, NulTerminatedStringPiece) { Font base_font; Font fallback_font; // Multiple ending NUL characters. - const base::char16 kTest1[] = {0x0540, 0x0541, 0, 0, 0}; + const char16_t kTest1[] = {0x0540, 0x0541, 0, 0, 0}; EXPECT_FALSE(GetFallbackFont(base_font, kDefaultApplicationLocale, base::StringPiece16(kTest1, base::size(kTest1)), &fallback_font)); // No ending NUL character. - const base::char16 kTest2[] = {0x0540, 0x0541}; + const char16_t kTest2[] = {0x0540, 0x0541}; EXPECT_TRUE(GetFallbackFont(base_font, kDefaultApplicationLocale, base::StringPiece16(kTest2, base::size(kTest2)), &fallback_font)); // NUL only characters. - const base::char16 kTest3[] = {0, 0, 0}; + const char16_t kTest3[] = {0, 0, 0}; EXPECT_FALSE(GetFallbackFont(base_font, kDefaultApplicationLocale, base::StringPiece16(kTest3, base::size(kTest3)), &fallback_font)); @@ -115,7 +115,7 @@ TEST_F(FontFallbackWinTest, CJKLocaleFallback) { // common feature of written Chinese (hanzi), Japanese (kanji), and Korean // (hanja). The same text will be rendered using a different font based on // locale. - const base::char16 kCJKTest[] = STRING16_LITERAL("\u8AA4\u904E\u9AA8"); + const char16_t kCJKTest[] = u"\u8AA4\u904E\u9AA8"; Font base_font; Font fallback_font; diff --git a/chromium/ui/gfx/font_unittest.cc b/chromium/ui/gfx/font_unittest.cc index 480a049f062..63872ad8c23 100644 --- a/chromium/ui/gfx/font_unittest.cc +++ b/chromium/ui/gfx/font_unittest.cc @@ -4,8 +4,9 @@ #include "ui/gfx/font.h" +#include + #include "base/macros.h" -#include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" diff --git a/chromium/ui/gfx/geometry/mojom/geometry.mojom b/chromium/ui/gfx/geometry/mojom/geometry.mojom index 7ed95f64baa..30c19923797 100644 --- a/chromium/ui/gfx/geometry/mojom/geometry.mojom +++ b/chromium/ui/gfx/geometry/mojom/geometry.mojom @@ -33,6 +33,7 @@ struct SizeF { float height; }; +[Stable] struct Rect { int32 x; int32 y; diff --git a/chromium/ui/gfx/geometry/scroll_offset.h b/chromium/ui/gfx/geometry/scroll_offset.h index 96e8d960896..a0e7e8ece40 100644 --- a/chromium/ui/gfx/geometry/scroll_offset.h +++ b/chromium/ui/gfx/geometry/scroll_offset.h @@ -20,8 +20,8 @@ namespace gfx { class GEOMETRY_EXPORT ScrollOffset { public: - ScrollOffset() : x_(0), y_(0) {} - ScrollOffset(float x, float y) : x_(x), y_(y) {} + constexpr ScrollOffset() : x_(0), y_(0) {} + constexpr ScrollOffset(float x, float y) : x_(x), y_(y) {} explicit ScrollOffset(const Vector2dF& v) : x_(v.x()), y_(v.y()) {} explicit ScrollOffset(const Vector2d& v) : x_(v.x()), y_(v.y()) {} diff --git a/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc b/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc index 86c3dceea29..2afa1ca9bba 100644 --- a/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc +++ b/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.cc @@ -94,20 +94,6 @@ ClientNativePixmapDmaBuf::PlaneInfo::~PlaneInfo() { bool ClientNativePixmapDmaBuf::IsConfigurationSupported( gfx::BufferFormat format, gfx::BufferUsage usage) { - bool disable_yuv_biplanar = true; -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMECAST) - // IsConfigurationSupported(SCANOUT_CPU_READ_WRITE) is used by the renderer - // to tell whether the platform supports sampling a given format. Zero-copy - // video capture and encoding requires gfx::BufferFormat::YUV_420_BIPLANAR to - // be supported by the renderer. Most of Chrome OS platforms support it, so - // enable it by default, with a switch that allows an explicit disable on - // platforms known to have problems, e.g. the Tegra-based nyan." - // TODO(crbug.com/982201): move gfx::BufferFormat::YUV_420_BIPLANAR out - // of if defined(ARCH_CPU_X86_FAMLIY) when Tegra is no longer supported. - disable_yuv_biplanar = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableYuv420Biplanar); -#endif - switch (usage) { case gfx::BufferUsage::GPU_READ: return format == gfx::BufferFormat::BGR_565 || @@ -123,6 +109,7 @@ bool ClientNativePixmapDmaBuf::IsConfigurationSupported( format == gfx::BufferFormat::BGRA_8888 || format == gfx::BufferFormat::RGBA_1010102 || format == gfx::BufferFormat::BGRA_1010102; + case gfx::BufferUsage::SCANOUT_FRONT_RENDERING: case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE: // TODO(crbug.com/954233): RG_88 is enabled only with // --enable-native-gpu-memory-buffers . Otherwise it breaks some telemetry @@ -130,10 +117,8 @@ bool ClientNativePixmapDmaBuf::IsConfigurationSupported( if (format == gfx::BufferFormat::RG_88 && !AllowCpuMappableBuffers()) return false; - if (!disable_yuv_biplanar && - format == gfx::BufferFormat::YUV_420_BIPLANAR) { + if (format == gfx::BufferFormat::YUV_420_BIPLANAR) return true; - } return #if defined(ARCH_CPU_X86_FAMILY) @@ -158,10 +143,8 @@ bool ClientNativePixmapDmaBuf::IsConfigurationSupported( if (!AllowCpuMappableBuffers()) return false; - if (!disable_yuv_biplanar && - format == gfx::BufferFormat::YUV_420_BIPLANAR) { + if (format == gfx::BufferFormat::YUV_420_BIPLANAR) return true; - } return #if defined(ARCH_CPU_X86_FAMILY) diff --git a/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc b/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc index 301b75bbb2e..f03678e4529 100644 --- a/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc +++ b/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc @@ -61,6 +61,7 @@ class ClientNativePixmapFactoryDmabuf : public ClientNativePixmapFactory { case gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE: case gfx::BufferUsage::SCANOUT_VEA_CPU_READ: case gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE: + case gfx::BufferUsage::SCANOUT_FRONT_RENDERING: return ClientNativePixmapDmaBuf::ImportFromDmabuf(std::move(handle), size, format); case gfx::BufferUsage::GPU_READ: diff --git a/chromium/ui/gfx/linux/gbm_defines.h b/chromium/ui/gfx/linux/gbm_defines.h index c139b377f9e..b663173cb6f 100644 --- a/chromium/ui/gfx/linux/gbm_defines.h +++ b/chromium/ui/gfx/linux/gbm_defines.h @@ -21,6 +21,7 @@ #define GBM_BO_USE_HW_VIDEO_ENCODER 0 #define GBM_BO_USE_PROTECTED 0 #define GBM_BO_USE_SW_READ_OFTEN 0 +#define GBM_BO_USE_FRONT_RENDERING 0 #endif #endif // UI_GFX_LINUX_GBM_DEFINES_H_ diff --git a/chromium/ui/gfx/linux/gbm_util.cc b/chromium/ui/gfx/linux/gbm_util.cc index e0ad3ddc030..76f5f62b9a0 100644 --- a/chromium/ui/gfx/linux/gbm_util.cc +++ b/chromium/ui/gfx/linux/gbm_util.cc @@ -37,9 +37,15 @@ uint32_t BufferUsageToGbmFlags(gfx::BufferUsage usage) { return GBM_BO_USE_LINEAR | GBM_BO_USE_CAMERA_WRITE | GBM_BO_USE_TEXTURING | GBM_BO_USE_HW_VIDEO_ENCODER | GBM_BO_USE_SW_READ_OFTEN; - default: + case gfx::BufferUsage::SCANOUT_FRONT_RENDERING: +// TODO(sashamcintosh): remove after crrev.com/c/2450927 is upreved +#ifdef GBM_BO_USE_FRONT_RENDERING + return GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING | + GBM_BO_USE_FRONT_RENDERING; +#else NOTREACHED(); return 0; +#endif } } diff --git a/chromium/ui/gfx/mojom/BUILD.gn b/chromium/ui/gfx/mojom/BUILD.gn index d52a4e96306..07b61c87c7c 100644 --- a/chromium/ui/gfx/mojom/BUILD.gn +++ b/chromium/ui/gfx/mojom/BUILD.gn @@ -12,6 +12,8 @@ mojom("mojom") { "buffer_types.mojom", "ca_layer_params.mojom", "color_space.mojom", + "delegated_ink_metadata.mojom", + "delegated_ink_point.mojom", "display_color_spaces.mojom", "font_render_params.mojom", "gpu_extra_info.mojom", @@ -30,6 +32,7 @@ mojom("mojom") { public_deps = [ ":native_handle_types", "//mojo/public/mojom/base", + "//skia/public/mojom", "//ui/gfx/geometry/mojom", ] @@ -184,6 +187,30 @@ mojom("mojom") { traits_headers = [ "ca_layer_params_mojom_traits.h" ] traits_public_deps = [ "//ui/gfx" ] }, + { + types = [ + { + mojom = "gfx.mojom.DelegatedInkMetadata" + cpp = "::std::unique_ptr<::gfx::DelegatedInkMetadata>" + move_only = true + nullable_is_same_type = true + }, + ] + traits_sources = [ "delegated_ink_metadata_mojom_traits.cc" ] + traits_headers = [ "delegated_ink_metadata_mojom_traits.h" ] + traits_public_deps = [ "//ui/gfx" ] + }, + { + types = [ + { + mojom = "gfx.mojom.DelegatedInkPoint" + cpp = "::gfx::DelegatedInkPoint" + }, + ] + traits_sources = [ "delegated_ink_point_mojom_traits.cc" ] + traits_headers = [ "delegated_ink_point_mojom_traits.h" ] + traits_public_deps = [ "//ui/gfx" ] + }, { types = [ { @@ -258,6 +285,20 @@ mojom("mojom") { cpp_typemaps += shared_cpp_typemaps blink_cpp_typemaps = shared_cpp_typemaps + blink_cpp_typemaps += [ + { + types = [ + { + mojom = "gfx.mojom.DelegatedInkMetadata" + cpp = "::std::unique_ptr<::gfx::DelegatedInkMetadata>" + move_only = true + nullable_is_same_type = true + }, + ] + traits_headers = [ "delegated_ink_metadata_mojom_traits.h" ] + traits_public_deps = [ "//ui/gfx" ] + }, + ] } mojom("native_handle_types") { diff --git a/chromium/ui/gfx/mojom/DEPS b/chromium/ui/gfx/mojom/DEPS index ef8ad28d9d4..507f9cdaad0 100644 --- a/chromium/ui/gfx/mojom/DEPS +++ b/chromium/ui/gfx/mojom/DEPS @@ -1,3 +1,9 @@ include_rules = [ "+mojo/public", ] + +specific_include_rules = { + "delegated_ink_metadata_mojom_traits\.h" : [ + "+skia/public/mojom/skcolor_mojom_traits.h", + ], +} \ No newline at end of file diff --git a/chromium/ui/gfx/mojom/buffer_types.mojom b/chromium/ui/gfx/mojom/buffer_types.mojom index 09647403fe2..ac5ea1cb625 100644 --- a/chromium/ui/gfx/mojom/buffer_types.mojom +++ b/chromium/ui/gfx/mojom/buffer_types.mojom @@ -37,6 +37,7 @@ enum BufferUsage { GPU_READ_CPU_READ_WRITE, SCANOUT_VEA_CPU_READ, VEA_READ_CAMERA_AND_CPU_READ_WRITE, + SCANOUT_FRONT_RENDERING, }; struct BufferUsageAndFormat { diff --git a/chromium/ui/gfx/mojom/buffer_types_mojom_traits.cc b/chromium/ui/gfx/mojom/buffer_types_mojom_traits.cc index 532c4a9edfb..9af344380cb 100644 --- a/chromium/ui/gfx/mojom/buffer_types_mojom_traits.cc +++ b/chromium/ui/gfx/mojom/buffer_types_mojom_traits.cc @@ -54,7 +54,9 @@ gfx::mojom::GpuMemoryBufferPlatformHandlePtr StructTraits< #if defined(OS_WIN) DCHECK(handle.dxgi_handle.IsValid()); return gfx::mojom::GpuMemoryBufferPlatformHandle::NewDxgiHandle( - mojo::PlatformHandle(std::move(handle.dxgi_handle))); + gfx::mojom::DxgiHandle::New( + mojo::PlatformHandle(std::move(handle.dxgi_handle)), + std::move(handle.region))); #else break; #endif @@ -137,7 +139,9 @@ bool StructTraitstype = gfx::DXGI_SHARED_HANDLE; - out->dxgi_handle = platform_handle->get_dxgi_handle().TakeHandle(); + auto dxgi_handle = std::move(platform_handle->get_dxgi_handle()); + out->dxgi_handle = dxgi_handle->buffer_handle.TakeHandle(); + out->region = std::move(dxgi_handle->shared_memory_handle); return true; } #elif defined(OS_ANDROID) diff --git a/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h b/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h index 4aa2ecf2ace..0a0e79a02da 100644 --- a/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h +++ b/chromium/ui/gfx/mojom/buffer_types_mojom_traits.h @@ -137,6 +137,8 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) return gfx::mojom::BufferUsage::SCANOUT_VEA_CPU_READ; case gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE: return gfx::mojom::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE; + case gfx::BufferUsage::SCANOUT_FRONT_RENDERING: + return gfx::mojom::BufferUsage::SCANOUT_FRONT_RENDERING; } NOTREACHED(); return gfx::mojom::BufferUsage::kMinValue; @@ -174,6 +176,9 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS) case gfx::mojom::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE: *out = gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE; return true; + case gfx::mojom::BufferUsage::SCANOUT_FRONT_RENDERING: + *out = gfx::BufferUsage::SCANOUT_FRONT_RENDERING; + return true; } NOTREACHED(); return false; diff --git a/chromium/ui/gfx/mojom/delegated_ink_metadata.mojom b/chromium/ui/gfx/mojom/delegated_ink_metadata.mojom new file mode 100644 index 00000000000..c3b5438888e --- /dev/null +++ b/chromium/ui/gfx/mojom/delegated_ink_metadata.mojom @@ -0,0 +1,20 @@ +// 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. + +module gfx.mojom; + +import "mojo/public/mojom/base/time.mojom"; +import "skia/public/mojom/skcolor.mojom"; +import "ui/gfx/geometry/mojom/geometry.mojom"; + +// See ui/gfx/delegated_ink_metadata.h. +struct DelegatedInkMetadata { + PointF point; + double diameter; + skia.mojom.SkColor color; + mojo_base.mojom.TimeTicks timestamp; + RectF presentation_area; + mojo_base.mojom.TimeTicks frame_time; + bool is_hovering; +}; diff --git a/chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.cc b/chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.cc new file mode 100644 index 00000000000..f3f10a896ab --- /dev/null +++ b/chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.cc @@ -0,0 +1,35 @@ +// 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/gfx/mojom/delegated_ink_metadata_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits>:: + Read(gfx::mojom::DelegatedInkMetadataDataView data, + std::unique_ptr* out) { + // Diameter isn't expected to ever be below 0, so stop here if it is in order + // to avoid unexpected calculations in viz. + if (data.diameter() < 0) + return false; + + gfx::PointF point; + base::TimeTicks timestamp; + gfx::RectF presentation_area; + SkColor color; + base::TimeTicks frame_time; + if (!data.ReadPoint(&point) || !data.ReadTimestamp(×tamp) || + !data.ReadPresentationArea(&presentation_area) || + !data.ReadColor(&color) || !data.ReadFrameTime(&frame_time)) { + return false; + } + *out = std::make_unique( + point, data.diameter(), color, timestamp, presentation_area, frame_time, + data.is_hovering()); + return true; +} + +} // namespace mojo diff --git a/chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.h b/chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.h new file mode 100644 index 00000000000..b9c875d1f5a --- /dev/null +++ b/chromium/ui/gfx/mojom/delegated_ink_metadata_mojom_traits.h @@ -0,0 +1,70 @@ +// 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_GFX_MOJOM_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_ +#define UI_GFX_MOJOM_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_ + +#include + +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "skia/public/mojom/skcolor_mojom_traits.h" +#include "ui/gfx/delegated_ink_metadata.h" +#include "ui/gfx/mojom/delegated_ink_metadata.mojom-shared.h" +#include "ui/gfx/mojom/rrect_f_mojom_traits.h" + +namespace mojo { + +template <> +struct StructTraits> { + static bool IsNull(const std::unique_ptr& input) { + return !input; + } + + static void SetToNull(std::unique_ptr* input) { + input->reset(); + } + + static const gfx::PointF& point( + const std::unique_ptr& input) { + return input->point(); + } + + static double diameter( + const std::unique_ptr& input) { + return input->diameter(); + } + + static SkColor color( + const std::unique_ptr& input) { + return input->color(); + } + + static base::TimeTicks timestamp( + const std::unique_ptr& input) { + return input->timestamp(); + } + + static const gfx::RectF& presentation_area( + const std::unique_ptr& input) { + return input->presentation_area(); + } + + static base::TimeTicks frame_time( + const std::unique_ptr& input) { + return input->frame_time(); + } + + static bool is_hovering( + const std::unique_ptr& input) { + return input->is_hovering(); + } + + static bool Read(gfx::mojom::DelegatedInkMetadataDataView data, + std::unique_ptr* out); +}; + +} // namespace mojo + +#endif // UI_GFX_MOJOM_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_ diff --git a/chromium/ui/gfx/mojom/delegated_ink_point.mojom b/chromium/ui/gfx/mojom/delegated_ink_point.mojom new file mode 100644 index 00000000000..8ed6561c1c7 --- /dev/null +++ b/chromium/ui/gfx/mojom/delegated_ink_point.mojom @@ -0,0 +1,15 @@ +// 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. + +module gfx.mojom; + +import "mojo/public/mojom/base/time.mojom"; +import "ui/gfx/geometry/mojom/geometry.mojom"; + +// See ui/gfx/delegated_ink_point.h. +struct DelegatedInkPoint { + PointF point; + mojo_base.mojom.TimeTicks timestamp; + int32 pointer_id; +}; diff --git a/chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.cc b/chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.cc new file mode 100644 index 00000000000..97fd785876b --- /dev/null +++ b/chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.cc @@ -0,0 +1,18 @@ +// 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/gfx/mojom/delegated_ink_point_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits< + gfx::mojom::DelegatedInkPointDataView, + gfx::DelegatedInkPoint>::Read(gfx::mojom::DelegatedInkPointDataView data, + gfx::DelegatedInkPoint* out) { + out->pointer_id_ = data.pointer_id(); + return data.ReadPoint(&out->point_) && data.ReadTimestamp(&out->timestamp_); +} + +} // namespace mojo diff --git a/chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.h b/chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.h new file mode 100644 index 00000000000..b188b302631 --- /dev/null +++ b/chromium/ui/gfx/mojom/delegated_ink_point_mojom_traits.h @@ -0,0 +1,36 @@ +// 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_GFX_MOJOM_DELEGATED_INK_POINT_MOJOM_TRAITS_H_ +#define UI_GFX_MOJOM_DELEGATED_INK_POINT_MOJOM_TRAITS_H_ + +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "ui/gfx/delegated_ink_point.h" +#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" +#include "ui/gfx/mojom/delegated_ink_point.mojom-shared.h" + +namespace mojo { + +template <> +struct StructTraits { + static const gfx::PointF& point(const gfx::DelegatedInkPoint& input) { + return input.point(); + } + + static base::TimeTicks timestamp(const gfx::DelegatedInkPoint& input) { + return input.timestamp(); + } + + static int32_t pointer_id(const gfx::DelegatedInkPoint& input) { + return input.pointer_id(); + } + + static bool Read(gfx::mojom::DelegatedInkPointDataView data, + gfx::DelegatedInkPoint* out); +}; + +} // namespace mojo + +#endif // UI_GFX_MOJOM_DELEGATED_INK_POINT_MOJOM_TRAITS_H_ diff --git a/chromium/ui/gfx/mojom/native_handle_types.mojom b/chromium/ui/gfx/mojom/native_handle_types.mojom index 5cf14615ca2..5b7be0a2123 100644 --- a/chromium/ui/gfx/mojom/native_handle_types.mojom +++ b/chromium/ui/gfx/mojom/native_handle_types.mojom @@ -8,7 +8,7 @@ import "mojo/public/mojom/base/shared_memory.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; // gfx::NativePixmapPlane -[EnableIf=supports_native_pixmap] +[EnableIf=supports_native_pixmap, Stable] struct NativePixmapPlane { uint32 stride; uint64 offset; @@ -50,6 +50,18 @@ struct AHardwareBufferHandle { handle tracking_pipe; }; +[EnableIf=is_win] +struct DxgiHandle { + // The actual buffer windows handle. + handle buffer_handle; + + // Shared memory copy of all the data. Valid only if requested by the + // consumer. It is included here because DXGI GMBs are unmappable except in + // the GPU process. So without it the consumer if a CPU readable frame is + // needed would resort to request a copy in the shared memory via GPU process. + mojo_base.mojom.UnsafeSharedMemoryRegion? shared_memory_handle; +}; + union GpuMemoryBufferPlatformHandle { mojo_base.mojom.UnsafeSharedMemoryRegion shared_memory_handle; @@ -60,7 +72,7 @@ union GpuMemoryBufferPlatformHandle { handle mach_port; [EnableIf=is_win] - handle dxgi_handle; + DxgiHandle dxgi_handle; [EnableIf=is_android] AHardwareBufferHandle android_hardware_buffer_handle; diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc index 8b6064d1599..c80c92f0841 100644 --- a/chromium/ui/gfx/render_text.cc +++ b/chromium/ui/gfx/render_text.cc @@ -47,7 +47,7 @@ namespace gfx { namespace { // Replacement codepoint for elided text. -constexpr base::char16 kEllipsisCodepoint = 0x2026; +constexpr char16_t kEllipsisCodepoint = 0x2026; // Fraction of the text size to raise the center of a strike-through line above // the baseline. @@ -200,10 +200,10 @@ typename BreakList::const_iterator IncrementBreakListIteratorToPosition( UChar32 ReplaceControlCharacter(UChar32 codepoint) { // 'REPLACEMENT CHARACTER' used to replace an unknown, // unrecognized or unrepresentable character. - constexpr base::char16 kReplacementCodepoint = 0xFFFD; + constexpr char16_t kReplacementCodepoint = 0xFFFD; // Control Pictures block (see: // https://unicode.org/charts/PDF/U2400.pdf). - constexpr base::char16 kSymbolsCodepoint = 0x2400; + constexpr char16_t kSymbolsCodepoint = 0x2400; if (codepoint >= 0 && codepoint <= 0x1F) { // Replace codepoints with their visual symbols, which are @@ -226,6 +226,12 @@ UChar32 ReplaceControlCharacter(UChar32 codepoint) { if (codepoint > 0x7F) { // Private use codepoints are working with a pair of font // and codepoint, but they are not used in Chrome. +#if defined(OS_MAC) + // Support Apple defined PUA on Mac. + // see: http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT + if (codepoint == 0xF8FF) + return codepoint; +#endif const int8_t codepoint_category = u_charType(codepoint); if (codepoint_category == U_PRIVATE_USE_CHAR || codepoint_category == U_CONTROL_CHAR) { @@ -427,7 +433,7 @@ void ApplyRenderParams(const FontRenderParams& params, } // namespace internal // static -constexpr base::char16 RenderText::kPasswordReplacementChar; +constexpr char16_t RenderText::kPasswordReplacementChar; constexpr bool RenderText::kDragToEndIfOutsideVerticalBounds; constexpr SkColor RenderText::kDefaultColor; constexpr SkColor RenderText::kDefaultSelectionBackgroundColor; @@ -442,7 +448,7 @@ std::unique_ptr RenderText::CreateRenderText() { } std::unique_ptr RenderText::CreateInstanceOfSameStyle( - const base::string16& text) const { + const std::u16string& text) const { std::unique_ptr render_text = CreateRenderText(); // |SetText()| must be called before styles are set. render_text->SetText(text); @@ -459,7 +465,7 @@ std::unique_ptr RenderText::CreateInstanceOfSameStyle( return render_text; } -void RenderText::SetText(const base::string16& text) { +void RenderText::SetText(const std::u16string& text) { DCHECK(!composition_range_.IsValid()); if (text_ == text) return; @@ -488,7 +494,7 @@ void RenderText::SetText(const base::string16& text) { OnTextAttributeChanged(); } -void RenderText::AppendText(const base::string16& text) { +void RenderText::AppendText(const std::u16string& text) { text_ += text; UpdateStyleLengths(); cached_bounds_and_offset_valid_ = false; @@ -1294,10 +1300,10 @@ bool RenderText::GetLookupDataForRange(const Range& range, return true; } -base::string16 RenderText::GetTextFromRange(const Range& range) const { +std::u16string RenderText::GetTextFromRange(const Range& range) const { if (range.IsValid() && range.GetMin() < text().length()) return text().substr(range.GetMin(), range.length()); - return base::string16(); + return std::u16string(); } Range RenderText::ExpandRangeToGraphemeBoundary(const Range& range) const { @@ -1317,7 +1323,7 @@ bool RenderText::IsNewlineSegment(const internal::LineSegment& segment) const { return IsNewlineSegment(text_, segment); } -bool RenderText::IsNewlineSegment(const base::string16& text, +bool RenderText::IsNewlineSegment(const std::u16string& text, const internal::LineSegment& segment) const { const size_t offset = segment.char_range.start(); const size_t length = segment.char_range.length(); @@ -1326,7 +1332,7 @@ bool RenderText::IsNewlineSegment(const base::string16& text, (length == 2 && text[offset] == '\r' && text[offset + 1] == '\n'); } -Range RenderText::GetLineRange(const base::string16& text, +Range RenderText::GetLineRange(const std::u16string& text, const internal::Line& line) const { // This will find the logical start and end indices of the given line. size_t max_index = 0; @@ -1603,7 +1609,7 @@ void RenderText::EnsureLayoutTextUpdated() const { layout_text_up_to_date_ = true; } -const base::string16& RenderText::GetLayoutText() const { +const std::u16string& RenderText::GetLayoutText() const { EnsureLayoutTextUpdated(); return layout_text_; } @@ -1646,9 +1652,9 @@ void RenderText::UpdateDisplayText(float text_width) { layout_text_, render_text->GetShapedText()->lines()[max_lines_ - 1]); // Add an ellipsis character in case the last line is short enough to fit // on a single line. Otherwise that character will be elided anyway. - base::string16 text_to_elide = + std::u16string text_to_elide = layout_text_.substr(line_range.start(), line_range.length()) + - base::string16(kEllipsisUTF16); + std::u16string(kEllipsisUTF16); display_text_.assign(layout_text_.substr(0, line_range.start()) + Elide(text_to_elide, 0, static_cast(display_rect_.width()), @@ -1672,7 +1678,7 @@ const BreakList& RenderText::GetLineBreaks() { if (line_breaks_.max() != 0) return line_breaks_; - const base::string16& layout_text = GetDisplayText(); + const std::u16string& layout_text = GetDisplayText(); const size_t text_length = layout_text.length(); line_breaks_.SetValue(0); line_breaks_.SetMax(text_length); @@ -1849,7 +1855,7 @@ void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { } base::i18n::TextDirection RenderText::GetTextDirectionForGivenText( - const base::string16& text) const { + const std::u16string& text) const { switch (directionality_mode_) { case DIRECTIONALITY_FROM_TEXT: // Derive the direction from the display text, which differs from text() @@ -2006,12 +2012,12 @@ void RenderText::OnTextAttributeChanged() { OnLayoutTextAttributeChanged(true); } -base::string16 RenderText::Elide(const base::string16& text, +std::u16string RenderText::Elide(const std::u16string& text, float text_width, float available_width, ElideBehavior behavior) { if (available_width <= 0 || text.empty()) - return base::string16(); + return std::u16string(); if (behavior == ELIDE_EMAIL) return ElideEmail(text, available_width); if (text_width > 0 && text_width <= available_width) @@ -2027,7 +2033,7 @@ base::string16 RenderText::Elide(const base::string16& text, if (text_width <= available_width) return text; - const base::string16 ellipsis = base::string16(kEllipsisUTF16); + const std::u16string ellipsis = std::u16string(kEllipsisUTF16); const bool insert_ellipsis = (behavior != TRUNCATE); const bool elide_in_middle = (behavior == ELIDE_MIDDLE); const bool elide_at_beginning = (behavior == ELIDE_HEAD); @@ -2036,7 +2042,7 @@ base::string16 RenderText::Elide(const base::string16& text, render_text->SetText(ellipsis); const float ellipsis_width = render_text->GetContentWidthF(); if (ellipsis_width > available_width) - return base::string16(); + return std::u16string(); } StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning, @@ -2073,7 +2079,7 @@ base::string16 RenderText::Elide(const base::string16& text, // Restore colors. They will be truncated to size by SetText. render_text->colors_ = colors_; - base::string16 new_text = + std::u16string new_text = slicer.CutString(guess, insert_ellipsis && behavior != ELIDE_TAIL); // This has to be an additional step so that the ellipsis is rendered with @@ -2145,7 +2151,7 @@ base::string16 RenderText::Elide(const base::string16& text, return render_text->text(); } -base::string16 RenderText::ElideEmail(const base::string16& email, +std::u16string RenderText::ElideEmail(const std::u16string& email, float available_width) { // The returned string will have at least one character besides the ellipsis // on either side of '@'; if that's impossible, a single ellipsis is returned. @@ -2158,23 +2164,23 @@ base::string16 RenderText::ElideEmail(const base::string16& email, // spec allows for @ symbols in the username under some special requirements, // but not in the domain part, so splitting at the last @ symbol is safe. const size_t split_index = email.find_last_of('@'); - if (split_index == base::string16::npos) + if (split_index == std::u16string::npos) return Elide(email, 0, available_width, ELIDE_TAIL); - base::string16 username = email.substr(0, split_index); - base::string16 domain = email.substr(split_index + 1); + std::u16string username = email.substr(0, split_index); + std::u16string domain = email.substr(split_index + 1); // TODO(http://crbug.com/1085014): Fix eliding of text with styles. DCHECK(IsHomogeneous()) << "ElideEmail(...) doesn't work with non homogeneous styles."; - auto render_text = CreateInstanceOfSameStyle(base::string16()); - auto get_string_width = [&](const base::string16& text) { + auto render_text = CreateInstanceOfSameStyle(std::u16string()); + auto get_string_width = [&](const std::u16string& text) { render_text->SetText(text); return render_text->GetStringSizeF().width(); }; // Subtract the @ symbol from the available width as it is mandatory. - const base::string16 kAtSignUTF16 = base::ASCIIToUTF16("@"); + const std::u16string kAtSignUTF16 = u"@"; float at_width = get_string_width(kAtSignUTF16); if (available_width < at_width) return Elide(kEllipsisUTF16, 0, available_width, ELIDE_TAIL); @@ -2263,7 +2269,7 @@ void RenderText::UpdateCachedBoundsAndOffset() { } internal::GraphemeIterator RenderText::GetGraphemeIteratorAtIndex( - const base::string16& text, + const std::u16string& text, const size_t internal::TextToDisplayIndex::*field, size_t index) const { DCHECK_LE(index, text.length()); diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h index bb7ce1ca82b..b4e825ddfb6 100644 --- a/chromium/ui/gfx/render_text.h +++ b/chromium/ui/gfx/render_text.h @@ -18,7 +18,6 @@ #include "base/i18n/rtl.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" #include "third_party/skia/include/core/SkColor.h" @@ -238,7 +237,7 @@ class GFX_EXPORT RenderText { // The character used for displaying obscured text. Use a bullet character. // TODO(pbos): This is highly font dependent, consider replacing the character // with a vector glyph. - static constexpr base::char16 kPasswordReplacementChar = 0x2022; + static constexpr char16_t kPasswordReplacementChar = 0x2022; virtual ~RenderText(); @@ -247,11 +246,11 @@ class GFX_EXPORT RenderText { // Like above but copies all style settings too. std::unique_ptr CreateInstanceOfSameStyle( - const base::string16& text) const; + const std::u16string& text) const; - const base::string16& text() const { return text_; } - void SetText(const base::string16& text); - void AppendText(const base::string16& text); + const std::u16string& text() const { return text_; } + void SetText(const std::u16string& text); + void AppendText(const std::u16string& text); HorizontalAlignment horizontal_alignment() const { return horizontal_alignment_; @@ -469,7 +468,7 @@ class GFX_EXPORT RenderText { // Returns the text used to display, which may be obscured, truncated or // elided. The subclass may compute elided text on the fly, or use // precomputed the elided text. - virtual const base::string16& GetDisplayText() = 0; + virtual const std::u16string& GetDisplayText() = 0; // Returns the size required to display the current string (which is the // wrapped size in multiline mode). The returned size does not include space @@ -608,7 +607,7 @@ class GFX_EXPORT RenderText { Point* baseline_point); // Retrieves the text in the given |range|. - base::string16 GetTextFromRange(const Range& range) const; + std::u16string GetTextFromRange(const Range& range) const; void set_strike_thickness_factor(SkScalar f) { strike_thickness_factor_ = f; } @@ -628,21 +627,21 @@ class GFX_EXPORT RenderText { bool IsNewlineSegment(const internal::LineSegment& segment) const; // Whether |segment| corresponds to the newline character inside |text|. - bool IsNewlineSegment(const base::string16& text, + bool IsNewlineSegment(const std::u16string& text, const internal::LineSegment& segment) const; // Returns the character range of segments in |line| excluding the trailing // newline segment. - Range GetLineRange(const base::string16& text, + Range GetLineRange(const std::u16string& text, const internal::Line& line) const; // Returns the text used for layout (e.g. after rewriting, eliding and // obscuring characters). - const base::string16& GetLayoutText() const; + const std::u16string& GetLayoutText() const; // NOTE: The value of these accessors may be stale. Please make sure // that these fields are up to date before accessing them. - const base::string16& display_text() const { return display_text_; } + const std::u16string& display_text() const { return display_text_; } bool text_elided() const { return text_elided_; } // Returns an iterator over the |text_| attributes. @@ -781,7 +780,7 @@ class GFX_EXPORT RenderText { // Get the text direction for the current directionality mode and given // |text|. base::i18n::TextDirection GetTextDirectionForGivenText( - const base::string16& text) const; + const std::u16string& text) const; // Adjust ranged styles to accommodate a new |text_| length. void UpdateStyleLengths(); @@ -839,13 +838,13 @@ class GFX_EXPORT RenderText { // Elides |text| as needed to fit in the |available_width| using |behavior|. // |text_width| is the pre-calculated width of the text shaped by this render // text, or pass 0 if the width is unknown. - base::string16 Elide(const base::string16& text, + std::u16string Elide(const std::u16string& text, float text_width, float available_width, ElideBehavior behavior); // Elides |email| as needed to fit the |available_width|. - base::string16 ElideEmail(const base::string16& email, float available_width); + std::u16string ElideEmail(const std::u16string& email, float available_width); // Update the cached bounds and display offset to ensure that the current // cursor is within the visible display area. @@ -856,7 +855,7 @@ class GFX_EXPORT RenderText { // Returns a grapheme iterator that contains the codepoint at |index|. internal::GraphemeIterator GetGraphemeIteratorAtIndex( - const base::string16& text, + const std::u16string& text, const size_t internal::TextToDisplayIndex::*field, size_t index) const; @@ -887,7 +886,7 @@ class GFX_EXPORT RenderText { } // Logical UTF-16 string data to be drawn. - base::string16 text_; + std::u16string text_; // Horizontal alignment of the text with respect to |display_rect_|. The // default is to align left if the application UI is LTR and right if RTL. @@ -974,14 +973,14 @@ class GFX_EXPORT RenderText { size_t truncate_length_ = 0; // The obscured and/or truncated text used to layout the text to display. - mutable base::string16 layout_text_; + mutable std::u16string layout_text_; // The elided text displayed visually. This is empty if the text // does not have to be elided, or became empty as a result of eliding. // TODO(oshima): When the text is elided, painting can be done only with // display text info, so it should be able to clear the |layout_text_| and // associated information. - mutable base::string16 display_text_; + mutable std::u16string display_text_; // The behavior for eliding, fading, or truncating. ElideBehavior elide_behavior_ = NO_ELIDE; diff --git a/chromium/ui/gfx/render_text_harfbuzz.cc b/chromium/ui/gfx/render_text_harfbuzz.cc index 29d3b45791f..17b28559427 100644 --- a/chromium/ui/gfx/render_text_harfbuzz.cc +++ b/chromium/ui/gfx/render_text_harfbuzz.cc @@ -240,7 +240,7 @@ bool AreGraphemePropertiesCompatible(const GraphemeProperties& first, // (see: UNICODE TEXT SEGMENTATION (http://unicode.org/reports/tr29/). // Breaks between |run_start| and |run_end| and force break after the grapheme // starting at |run_break|. -size_t FindRunBreakingCharacter(const base::string16& text, +size_t FindRunBreakingCharacter(const std::u16string& text, UScriptCode script, size_t run_start, size_t run_break, @@ -300,7 +300,7 @@ size_t FindRunBreakingCharacter(const base::string16& text, // Consider 3 characters with the script values {Kana}, {Hira, Kana}, {Kana}. // Without script extensions only the first script in each set would be taken // into account, resulting in 3 runs where 1 would be enough. -size_t ScriptInterval(const base::string16& text, +size_t ScriptInterval(const std::u16string& text, size_t start, size_t length, UScriptCode* script) { @@ -342,7 +342,7 @@ void MarkFontAsTried(sk_sp typeface, } // Whether |segment| corresponds to the newline character. -bool IsNewlineSegment(const base::string16& text, +bool IsNewlineSegment(const std::u16string& text, const internal::LineSegment& segment) { const size_t offset = segment.char_range.start(); const size_t length = segment.char_range.length(); @@ -355,7 +355,7 @@ bool IsNewlineSegment(const base::string16& text, // incremented if the caret is right after the newline character, i.e, the // cursor affinity is |CURSOR_BACKWARD| while containing the newline character. size_t LineIndexForNewline(const size_t line_index, - const base::string16& text, + const std::u16string& text, const internal::LineSegment& segment, const SelectionModel& caret) { bool at_newline = IsNewlineSegment(text, segment) && @@ -411,7 +411,7 @@ class HarfBuzzLineBreaker { float min_height, float glyph_height_for_test, WordWrapBehavior word_wrap_behavior, - const base::string16& text, + const std::u16string& text, const BreakList* words, const internal::TextRunList& run_list) : max_width_((max_width == 0) ? SK_ScalarMax : SkIntToScalar(max_width)), @@ -740,7 +740,7 @@ class HarfBuzzLineBreaker { const float min_height_; const float glyph_height_for_test_; const WordWrapBehavior word_wrap_behavior_; - const base::string16& text_; + const std::u16string& text_; const BreakList* const words_; const internal::TextRunList& run_list_; @@ -1184,7 +1184,7 @@ namespace { // Input for the stateless implementation of ShapeRunWithFont. struct ShapeRunWithFontInput { - ShapeRunWithFontInput(const base::string16& full_text, + ShapeRunWithFontInput(const std::u16string& full_text, const TextRunHarfBuzz::FontParams& font_params, Range full_range, bool obscured, @@ -1253,7 +1253,7 @@ struct ShapeRunWithFontInput { bool subpixel_rendering_suppressed; // The parts of the input text that may be read by hb_buffer_add_utf16. - base::string16 text; + std::u16string text; // The conversion of the input range to a range within |text|. Range range; // The hash is cached to avoid repeated calls. @@ -1381,7 +1381,7 @@ RenderTextHarfBuzz::RenderTextHarfBuzz() RenderTextHarfBuzz::~RenderTextHarfBuzz() {} -const base::string16& RenderTextHarfBuzz::GetDisplayText() { +const std::u16string& RenderTextHarfBuzz::GetDisplayText() { // TODO(krb): Consider other elision modes for multiline. if ((multiline() && (max_lines() == 0 || elide_behavior() != ELIDE_TAIL)) || elide_behavior() == NO_ELIDE || elide_behavior() == FADE_TAIL) { @@ -1674,7 +1674,7 @@ void RenderTextHarfBuzz::EnsureLayout() { if (update_display_run_list_) { DCHECK(text_elided()); - const base::string16& display_text = GetDisplayText(); + const std::u16string& display_text = GetDisplayText(); display_run_list_ = std::make_unique(); if (!display_text.empty()) @@ -1737,7 +1737,7 @@ void RenderTextHarfBuzz::DrawVisualText(internal::SkiaTextRenderer* renderer, } internal::TextRunList* run_list = GetRunList(); - const base::string16& display_text = GetDisplayText(); + const std::u16string& display_text = GetDisplayText(); for (size_t i = 0; i < shaped_text->lines().size(); ++i) { const internal::Line& line = shaped_text->lines()[i]; const Vector2d origin = GetLineOffset(i) + Vector2d(0, line.baseline); @@ -1831,7 +1831,7 @@ SelectionModel RenderTextHarfBuzz::LastSelectionModelInsideRun( return SelectionModel(position, CURSOR_FORWARD); } -void RenderTextHarfBuzz::ItemizeAndShapeText(const base::string16& text, +void RenderTextHarfBuzz::ItemizeAndShapeText(const std::u16string& text, internal::TextRunList* run_list) { CommonizedRunsMap commonized_run_map; ItemizeTextToRuns(text, run_list, &commonized_run_map); @@ -1848,7 +1848,7 @@ void RenderTextHarfBuzz::ItemizeAndShapeText(const base::string16& text, } void RenderTextHarfBuzz::ItemizeTextToRuns( - const base::string16& text, + const std::u16string& text, internal::TextRunList* out_run_list, CommonizedRunsMap* out_commonized_run_map) { TRACE_EVENT1("ui", "RenderTextHarfBuzz::ItemizeTextToRuns", "text_length", @@ -1942,34 +1942,10 @@ void RenderTextHarfBuzz::ItemizeTextToRuns( // Move to the next direction sequence. bidi_run_start = bidi_run_end; } - - // Add trace event to track incorrect usage of fallback fonts. - // TODO(https://crbug.com/995789): Remove the following code when the issue - // is fixed. - bool tracing_enabled; - TRACE_EVENT_CATEGORY_GROUP_ENABLED("fonts", &tracing_enabled); - if (tracing_enabled) { - std::string logging_str; - for (const auto& iter : *out_commonized_run_map) { - const internal::TextRunHarfBuzz::FontParams& font_params = iter.first; - for (const auto* run : iter.second) { - base::i18n::UTF16CharIterator text_iter(base::StringPiece16( - text.c_str() + run->range.start(), run->range.length())); - const UChar32 first_char = text_iter.get(); - const UBlockCode first_block = ublock_getCode(first_char); - const char* script_name = uscript_getShortName(font_params.script); - base::StringAppendF(&logging_str, "block=%d script=%s\n", - static_cast(first_block), - script_name ? script_name : ""); - } - } - TRACE_EVENT_INSTANT1("fonts", "RenderTextHarfBuzz::ItemizeTextToRuns::Runs", - TRACE_EVENT_SCOPE_THREAD, "runs", logging_str); - } } void RenderTextHarfBuzz::ShapeRuns( - const base::string16& text, + const std::u16string& text, const internal::TextRunHarfBuzz::FontParams& font_params, std::vector runs) { TRACE_EVENT1("ui", "RenderTextHarfBuzz::ShapeRuns", "run_count", runs.size()); @@ -2154,7 +2130,7 @@ void RenderTextHarfBuzz::ShapeRuns( } void RenderTextHarfBuzz::ShapeRunsWithFont( - const base::string16& text, + const std::u16string& text, const internal::TextRunHarfBuzz::FontParams& font_params, std::vector* in_out_runs) { // ShapeRunWithFont can be extremely slow, so use cached results if possible. @@ -2209,7 +2185,7 @@ void RenderTextHarfBuzz::EnsureLayoutRunList() { device_scale_factor_ = device_scale_factor; layout_run_list_.Reset(); - const base::string16& text = GetLayoutText(); + const std::u16string& text = GetLayoutText(); if (!text.empty()) ItemizeAndShapeText(text, &layout_run_list_); diff --git a/chromium/ui/gfx/render_text_harfbuzz.h b/chromium/ui/gfx/render_text_harfbuzz.h index f134c9fa655..40d7cc919a0 100644 --- a/chromium/ui/gfx/render_text_harfbuzz.h +++ b/chromium/ui/gfx/render_text_harfbuzz.h @@ -207,7 +207,7 @@ class GFX_EXPORT RenderTextHarfBuzz : public RenderText { ~RenderTextHarfBuzz() override; // RenderText: - const base::string16& GetDisplayText() override; + const std::u16string& GetDisplayText() override; SizeF GetStringSizeF() override; SizeF GetLineSizeF(const SelectionModel& caret) override; std::vector GetSubstringBounds(const Range& range) override; @@ -255,7 +255,7 @@ class GFX_EXPORT RenderTextHarfBuzz : public RenderText { // Break the text into logical runs in |out_run_list|. Populate // |out_commonized_run_map| such that each run is present in the vector // corresponding to its FontParams. - void ItemizeTextToRuns(const base::string16& string, + void ItemizeTextToRuns(const std::u16string& string, internal::TextRunList* out_run_list, CommonizedRunsMap* out_commonized_run_map); @@ -263,7 +263,7 @@ class GFX_EXPORT RenderTextHarfBuzz : public RenderText { // will apply a number of fonts to |base_font_params| and assign to each // run's FontParams and ShapeOutput the parameters and resulting shape that // had the smallest number of missing glyphs. - void ShapeRuns(const base::string16& text, + void ShapeRuns(const std::u16string& text, const internal::TextRunHarfBuzz::FontParams& base_font_params, std::vector runs); @@ -274,13 +274,13 @@ class GFX_EXPORT RenderTextHarfBuzz : public RenderText { // runs with no missing glyphs from |in_out_runs| (the caller, ShapeRuns, will // terminate when no runs with missing glyphs remain). void ShapeRunsWithFont( - const base::string16& text, + const std::u16string& text, const internal::TextRunHarfBuzz::FontParams& font_params, std::vector* in_out_runs); // Itemize |text| into runs in |out_run_list|, shape the runs, and populate // |out_run_list|'s visual <-> logical maps. - void ItemizeAndShapeText(const base::string16& text, + void ItemizeAndShapeText(const std::u16string& text, internal::TextRunList* out_run_list); // Makes sure that text runs for layout text are shaped. diff --git a/chromium/ui/gfx/render_text_test_api.h b/chromium/ui/gfx/render_text_test_api.h index 1de8993c8fb..b794efb9bbb 100644 --- a/chromium/ui/gfx/render_text_test_api.h +++ b/chromium/ui/gfx/render_text_test_api.h @@ -42,7 +42,7 @@ class RenderTextTestApi { render_text_->Draw(canvas, select_all); } - const base::string16& GetLayoutText() { + const std::u16string& GetLayoutText() { return render_text_->GetLayoutText(); } diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc index 1b25f807e95..1e71a0d8b60 100644 --- a/chromium/ui/gfx/render_text_unittest.cc +++ b/chromium/ui/gfx/render_text_unittest.cc @@ -49,6 +49,8 @@ #include "ui/gfx/text_utils.h" #if defined(OS_WIN) +#include + #include "base/win/windows_version.h" #endif @@ -104,7 +106,7 @@ bool IndexInRange(const Range& range, size_t index) { return index >= range.start() && index < range.end(); } -base::string16 GetSelectedText(RenderText* render_text) { +std::u16string GetSelectedText(RenderText* render_text) { return render_text->text().substr(render_text->selection().GetMin(), render_text->selection().length()); } @@ -240,23 +242,23 @@ void VerifyDecoratedWordsAreEqual(const DecoratedText& expected, // Helper method to return an obscured string of the given |length|, with the // |reveal_index| filled with |reveal_char|. -base::string16 GetObscuredString(size_t length, +std::u16string GetObscuredString(size_t length, size_t reveal_index, - base::char16 reveal_char) { - std::vector arr(length, RenderText::kPasswordReplacementChar); + char16_t reveal_char) { + std::vector arr(length, RenderText::kPasswordReplacementChar); arr[reveal_index] = reveal_char; - return base::string16(arr.begin(), arr.end()); + return std::u16string(arr.begin(), arr.end()); } // Helper method to return an obscured string of the given |length|. -base::string16 GetObscuredString(size_t length) { - return base::string16(length, RenderText::kPasswordReplacementChar); +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 ToString16Vec( +std::vector ToString16Vec( const std::vector& utf8_literals) { - std::vector vec; + std::vector vec; for (auto* const literal : utf8_literals) vec.push_back(UTF8ToUTF16(literal)); return vec; @@ -525,8 +527,8 @@ class RenderTextTest : public testing::Test { // Returns a vector of text fragments corresponding to the current list of // text runs. - std::vector GetRunListStrings() { - std::vector runs_as_text; + std::vector GetRunListStrings() { + std::vector runs_as_text; for (const auto& span : GetFontSpans()) { runs_as_text.push_back(render_text_->text().substr(span.second.GetMin(), span.second.length())); @@ -535,7 +537,7 @@ class RenderTextTest : public testing::Test { } // Sets the text to |text|, then returns GetRunListStrings(). - std::vector RunsFor(const base::string16& text) { + std::vector RunsFor(const std::u16string& text) { render_text_->SetText(text); test_api()->EnsureLayout(); return GetRunListStrings(); @@ -616,7 +618,7 @@ class RenderTextTest : public testing::Test { test_api()->SetGlyphHeight(test_height); } - bool ShapeRunWithFont(const base::string16& text, + bool ShapeRunWithFont(const std::u16string& text, const Font& font, const FontRenderParams& render_params, internal::TextRunHarfBuzz* run) { @@ -713,7 +715,7 @@ TEST_F(RenderTextTest, SetStyles) { TEST_F(RenderTextTest, ApplyStyles) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("012345678")); + render_text->SetText(u"012345678"); constexpr int kTestFontSizeOverride = 20; @@ -768,21 +770,21 @@ TEST_F(RenderTextTest, ApplyStyles) { expected_italic)); // Changing the text should clear any breaks except for the first one. - render_text->SetText(ASCIIToUTF16("0123456")); + render_text->SetText(u"0123456"); expected_italic.resize(1); EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting( expected_italic)); render_text->ApplyStyle(TEXT_STYLE_ITALIC, false, Range(2, 4)); - render_text->SetText(ASCIIToUTF16("012345678")); + render_text->SetText(u"012345678"); EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting( expected_italic)); render_text->ApplyStyle(TEXT_STYLE_ITALIC, false, Range(0, 1)); - render_text->SetText(ASCIIToUTF16("0123456")); + render_text->SetText(u"0123456"); expected_italic.begin()->second = false; EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting( expected_italic)); render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, Range(2, 4)); - render_text->SetText(ASCIIToUTF16("012345678")); + render_text->SetText(u"012345678"); EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_ITALIC].EqualsForTesting( expected_italic)); @@ -796,7 +798,7 @@ TEST_F(RenderTextTest, ApplyStyles) { TEST_F(RenderTextTest, ApplyStyleSurrogatePair) { RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(L"x\U0001F601x")); + render_text->SetText(u"x\U0001F601x"); // Apply the style in the middle of a surrogate pair. The style should be // applied to the whole range of the codepoint. gfx::Range range(2, 3); @@ -843,7 +845,7 @@ TEST_F(RenderTextTest, ApplyStyleMultipleGraphemes) { TEST_F(RenderTextTest, ApplyColorSurrogatePair) { RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(L"x\U0001F601x")); + render_text->SetText(u"x\U0001F601x"); render_text->ApplyColor(SK_ColorRED, Range(2, 3)); Draw(); @@ -860,12 +862,12 @@ TEST_F(RenderTextTest, ApplyColorSurrogatePair) { TEST_F(RenderTextTest, ApplyColorLongEmoji) { // A long emoji sequence. - static const wchar_t kLongEmoji[] = L"\U0001F468\u200D\u2708\uFE0F"; + static const char16_t kLongEmoji[] = u"\U0001F468\u200D\u2708\uFE0F"; RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(kLongEmoji)); - render_text->AppendText(WideToUTF16(kLongEmoji)); - render_text->AppendText(WideToUTF16(kLongEmoji)); + render_text->SetText(kLongEmoji); + render_text->AppendText(kLongEmoji); + render_text->AppendText(kLongEmoji); render_text->ApplyColor(SK_ColorRED, Range(0, 2)); render_text->ApplyColor(SK_ColorBLUE, Range(8, 13)); @@ -889,7 +891,7 @@ TEST_F(RenderTextTest, ApplyColorLongEmoji) { TEST_F(RenderTextTest, ApplyColorObscuredEmoji) { RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(L"\U0001F628\U0001F628\U0001F628")); + render_text->SetText(u"\U0001F628\U0001F628\U0001F628"); render_text->ApplyColor(SK_ColorRED, Range(0, 2)); render_text->ApplyColor(SK_ColorBLUE, Range(4, 5)); @@ -983,7 +985,7 @@ TEST_F(RenderTextTest, ApplyColorArabicLigature) { TEST_F(RenderTextTest, AppendTextKeepsStyles) { RenderText* render_text = GetRenderText(); // Setup basic functionality. - render_text->SetText(ASCIIToUTF16("abcd")); + render_text->SetText(u"abcd"); render_text->ApplyColor(SK_ColorRED, Range(0, 1)); render_text->ApplyBaselineStyle(SUPERSCRIPT, Range(1, 2)); render_text->ApplyStyle(TEXT_STYLE_UNDERLINE, true, Range(2, 3)); @@ -1005,8 +1007,8 @@ TEST_F(RenderTextTest, AppendTextKeepsStyles) { test_api()->font_size_overrides().EqualsForTesting(expected_font_size)); // Ensure AppendText maintains current text styles. - render_text->AppendText(ASCIIToUTF16("efg")); - EXPECT_EQ(render_text->GetDisplayText(), ASCIIToUTF16("abcdefg")); + render_text->AppendText(u"efg"); + EXPECT_EQ(render_text->GetDisplayText(), u"abcdefg"); EXPECT_TRUE(test_api()->colors().EqualsForTesting(expected_color)); EXPECT_TRUE(test_api()->baselines().EqualsForTesting(expected_baseline)); EXPECT_TRUE(test_api()->styles()[TEXT_STYLE_UNDERLINE].EqualsForTesting( @@ -1018,7 +1020,7 @@ TEST_F(RenderTextTest, AppendTextKeepsStyles) { TEST_F(RenderTextTest, SetSelection) { RenderText* render_text = GetRenderText(); render_text->set_selection_color(SK_ColorRED); - render_text->SetText(ASCIIToUTF16("abcdef")); + render_text->SetText(u"abcdef"); render_text->set_focused(true); // Single selection @@ -1040,7 +1042,7 @@ TEST_F(RenderTextTest, SetSelection) { TEST_F(RenderTextTest, SelectRangeColored) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdef")); + render_text->SetText(u"abcdef"); render_text->SetColor(SK_ColorBLACK); render_text->set_selection_color(SK_ColorRED); render_text->set_focused(true); @@ -1119,7 +1121,7 @@ TEST_F(RenderTextTest, SelectRangeColoredGrapheme) { TEST_F(RenderTextTest, SelectRangeMultiple) { RenderText* render_text = GetRenderText(); render_text->set_selection_color(SK_ColorRED); - render_text->SetText(ASCIIToUTF16("abcdef")); + render_text->SetText(u"abcdef"); render_text->set_focused(true); // Multiple selections @@ -1140,7 +1142,7 @@ TEST_F(RenderTextTest, SelectRangeMultiple) { TEST_F(RenderTextTest, SetCompositionRangeColored) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdef")); + render_text->SetText(u"abcdef"); render_text->SetCompositionRange(Range(0, 1)); Draw(); @@ -1174,7 +1176,7 @@ TEST_F(RenderTextTest, SetCompositionRangeColoredGrapheme) { void TestVisualCursorMotionInObscuredField( RenderText* render_text, - const base::string16& text, + const std::u16string& text, SelectionBehavior selection_behavior) { const bool select = selection_behavior != SELECTION_NONE; ASSERT_TRUE(render_text->obscured()); @@ -1203,8 +1205,8 @@ void TestVisualCursorMotionInObscuredField( } TEST_F(RenderTextTest, ObscuredText) { - const base::string16 seuss = ASCIIToUTF16("hop on pop"); - const base::string16 no_seuss = GetObscuredString(seuss.length()); + const std::u16string seuss = u"hop on pop"; + const std::u16string no_seuss = GetObscuredString(seuss.length()); RenderText* render_text = GetRenderText(); // GetDisplayText() returns a string filled with @@ -1220,10 +1222,10 @@ TEST_F(RenderTextTest, ObscuredText) { render_text->SetObscured(true); // Surrogate pairs are counted as one code point. - const base::char16 invalid_surrogates[] = {0xDC00, 0xD800, 0}; + const char16_t invalid_surrogates[] = {0xDC00, 0xD800, 0}; render_text->SetText(invalid_surrogates); EXPECT_EQ(GetObscuredString(2), render_text->GetDisplayText()); - const base::char16 valid_surrogates[] = {0xD800, 0xDC00, 0}; + const char16_t valid_surrogates[] = {0xD800, 0xDC00, 0}; render_text->SetText(valid_surrogates); EXPECT_EQ(GetObscuredString(1), render_text->GetDisplayText()); EXPECT_EQ(0U, render_text->cursor_position()); @@ -1265,42 +1267,42 @@ TEST_F(RenderTextTest, ObscuredText) { "\u05d0\u05d1 \u05d0\u05d2 \u05d1\u05d2", // Check RTL word boundaries. }; for (size_t i = 0; i < base::size(texts); ++i) { - base::string16 text = UTF8ToUTF16(texts[i]); + std::u16string text = UTF8ToUTF16(texts[i]); TestVisualCursorMotionInObscuredField(render_text, text, SELECTION_NONE); TestVisualCursorMotionInObscuredField(render_text, text, SELECTION_RETAIN); } } TEST_F(RenderTextTest, ObscuredTextMultiline) { - const base::string16 test = ASCIIToUTF16("a\nbc\ndef"); + const std::u16string test = u"a\nbc\ndef"; RenderText* render_text = GetRenderText(); render_text->SetText(test); render_text->SetObscured(true); render_text->SetMultiline(true); // Newlines should be kept in multiline mode. - base::string16 display_text = render_text->GetDisplayText(); + std::u16string display_text = render_text->GetDisplayText(); EXPECT_EQ(display_text[1], '\n'); EXPECT_EQ(display_text[4], '\n'); } TEST_F(RenderTextTest, ObscuredTextMultilineNewline) { - const base::string16 test = ASCIIToUTF16("\r\r\n"); + const std::u16string test = u"\r\r\n"; RenderText* render_text = GetRenderText(); render_text->SetText(test); render_text->SetObscured(true); render_text->SetMultiline(true); // Newlines should be kept in multiline mode. - base::string16 display_text = render_text->GetDisplayText(); + std::u16string display_text = render_text->GetDisplayText(); EXPECT_EQ(display_text[0], '\r'); EXPECT_EQ(display_text[1], '\r'); EXPECT_EQ(display_text[2], '\n'); } TEST_F(RenderTextTest, RevealObscuredText) { - const base::string16 seuss = ASCIIToUTF16("hop on pop"); - const base::string16 no_seuss = GetObscuredString(seuss.length()); + const std::u16string seuss = u"hop on pop"; + const std::u16string no_seuss = GetObscuredString(seuss.length()); RenderText* render_text = GetRenderText(); render_text->SetText(seuss); @@ -1335,16 +1337,16 @@ TEST_F(RenderTextTest, RevealObscuredText) { EXPECT_EQ(no_seuss, render_text->GetDisplayText()); // SetText clears the revealed index. - render_text->SetText(ASCIIToUTF16("new")); + render_text->SetText(u"new"); EXPECT_EQ(GetObscuredString(3), render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(2); EXPECT_EQ(GetObscuredString(3, 2, 'w'), render_text->GetDisplayText()); - render_text->SetText(ASCIIToUTF16("new longer")); + render_text->SetText(u"new longer"); EXPECT_EQ(GetObscuredString(10), render_text->GetDisplayText()); // Text with invalid surrogates (surrogates low 0xDC00 and high 0xD800). // Invalid surrogates are replaced by replacement character (e.g. 0xFFFD). - const base::char16 invalid_surrogates[] = {0xDC00, 0xD800, 'h', 'o', 'p', 0}; + const char16_t invalid_surrogates[] = {0xDC00, 0xD800, 'h', 'o', 'p', 0}; render_text->SetText(invalid_surrogates); EXPECT_EQ(GetObscuredString(5), render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(0); @@ -1355,33 +1357,31 @@ TEST_F(RenderTextTest, RevealObscuredText) { EXPECT_EQ(GetObscuredString(5, 2, 'h'), render_text->GetDisplayText()); // Text with valid surrogates before and after the reveal index. - const base::char16 valid_surrogates[] = - {0xD800, 0xDC00, 'h', 'o', 'p', 0xD800, 0xDC00, 0}; + const char16_t valid_surrogates[] = {0xD800, 0xDC00, 'h', 'o', + 'p', 0xD800, 0xDC00, 0}; render_text->SetText(valid_surrogates); EXPECT_EQ(GetObscuredString(5), render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(0); - const base::char16 valid_expect_0_and_1[] = { - 0xD800, - 0xDC00, - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, - 0}; + const char16_t valid_expect_0_and_1[] = {0xD800, + 0xDC00, + RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + 0}; EXPECT_EQ(valid_expect_0_and_1, render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(1); EXPECT_EQ(valid_expect_0_and_1, render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(2); EXPECT_EQ(GetObscuredString(5, 1, 'h'), render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(5); - const base::char16 valid_expect_5_and_6[] = { - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, - 0xD800, - 0xDC00, - 0}; + const char16_t valid_expect_5_and_6[] = {RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + 0xD800, + 0xDC00, + 0}; EXPECT_EQ(valid_expect_5_and_6, render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(6); EXPECT_EQ(valid_expect_5_and_6, render_text->GetDisplayText()); @@ -1393,7 +1393,7 @@ TEST_F(RenderTextTest, ObscuredEmoji) { 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(WideToUTF16(L"\U0001F601y")); + render_text->SetText(u"\U0001F601y"); render_text->Draw(canvas()); // Emoji codepoints are replaced by bullets (e.g. "\u2022\u2022"). @@ -1411,7 +1411,7 @@ TEST_F(RenderTextTest, ObscuredEmoji) { // Test two U+1F4F7 📷 "Camera" characters in a row. // Windows requires wide strings for \Unnnnnnnn universal character names. - render_text->SetText(WideToUTF16(L"\U0001F4F7\U0001F4F7")); + render_text->SetText(u"\U0001F4F7\U0001F4F7"); render_text->Draw(canvas()); // Emoji codepoints are replaced by bullets (e.g. "\u2022\u2022"). @@ -1428,7 +1428,7 @@ TEST_F(RenderTextTest, ObscuredEmoji) { render_text->SetObscuredRevealIndex(0); render_text->Draw(canvas()); - EXPECT_EQ(WideToUTF16(L"\U0001F4F7\u2022"), render_text->GetDisplayText()); + EXPECT_EQ(u"\U0001F4F7\u2022", 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 +1442,7 @@ TEST_F(RenderTextTest, ObscuredEmoji) { TEST_F(RenderTextTest, ObscuredEmojiRevealed) { RenderText* render_text = GetRenderText(); - base::string16 text = WideToUTF16(L"123\U0001F4F7\U0001F4F7x\U0001F601-"); + std::u16string text = u"123\U0001F4F7\U0001F4F7x\U0001F601-"; for (size_t i = 0; i < text.length(); ++i) { render_text->SetText(text); render_text->SetObscured(true); @@ -1484,8 +1484,8 @@ TEST_P(RenderTextTestWithTextIndexConversionCase, TextIndexConversion) { render_text->SetObscuredRevealIndex(reveal_index); render_text->Draw(canvas()); - base::string16 text = render_text->text(); - base::string16 display_text = render_text->GetDisplayText(); + std::u16string text = render_text->text(); + std::u16string display_text = render_text->GetDisplayText(); // Adjust reveal_index to point to the beginning of the surrogate pair, if // needed. @@ -1931,8 +1931,8 @@ TEST_P(RenderTextTestWithElideTextCase, ElideText) { const ElideTextTestOptions options = std::get<0>(GetParam()); const ElideTextCase param = std::get<1>(GetParam()); - const base::string16 text = WideToUTF16(param.text); - const base::string16 display_text = WideToUTF16(param.display_text); + const std::u16string text = WideToUTF16(param.text); + const std::u16string display_text = WideToUTF16(param.display_text); // Retrieve the display_text width without eliding. RenderTextHarfBuzz* render_text = GetRenderText(); @@ -2257,7 +2257,7 @@ TEST_F(RenderTextTest, ElidedText_NoTrimWhitespace) { // and not like: // [... ] constexpr char kInputString[] = " foo"; - const base::string16 input = ASCIIToUTF16(kInputString); + const std::u16string input = ASCIIToUTF16(kInputString); render_text->SetText(input); // Choose a width based on being able to display 12 characters (one of which @@ -2270,8 +2270,8 @@ TEST_F(RenderTextTest, ElidedText_NoTrimWhitespace) { EXPECT_EQ(input, render_text->text()); // Verify that the string is truncated to |kDesiredChars| with the ellipsis. - const base::string16 result = render_text->GetDisplayText(); - const base::string16 expected = + const std::u16string result = render_text->GetDisplayText(); + const std::u16string expected = input.substr(0, kDesiredChars - 1) + kEllipsisUTF16[0]; EXPECT_EQ(expected, result); } @@ -2282,15 +2282,15 @@ TEST_F(RenderTextTest, SetElideBehavior) { SetGlyphWidth(kGlyphWidth); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdef")); + render_text->SetText(u"abcdef"); render_text->SetCursorEnabled(false); render_text->SetDisplayRect(Rect(0, 0, 3 * kGlyphWidth, 100)); render_text->SetElideBehavior(ELIDE_TAIL); - EXPECT_EQ(WideToUTF16(L"ab\u2026"), render_text->GetDisplayText()); + EXPECT_EQ(u"ab\u2026", render_text->GetDisplayText()); // Setting a different eliding behavior must trigger a relayout. render_text->SetElideBehavior(ELIDE_HEAD); - EXPECT_EQ(WideToUTF16(L"\u2026ef"), render_text->GetDisplayText()); + EXPECT_EQ(u"\u2026ef", render_text->GetDisplayText()); } TEST_F(RenderTextTest, SetWhitespaceElision) { @@ -2299,24 +2299,24 @@ TEST_F(RenderTextTest, SetWhitespaceElision) { SetGlyphWidth(kGlyphWidth); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("a b c d")); + render_text->SetText(u"a b c d"); render_text->SetCursorEnabled(false); render_text->SetDisplayRect(Rect(0, 0, 3 * kGlyphWidth, 100)); render_text->SetElideBehavior(ELIDE_TAIL); render_text->SetWhitespaceElision(false); - EXPECT_EQ(WideToUTF16(L"a \u2026"), render_text->GetDisplayText()); + EXPECT_EQ(u"a \u2026", render_text->GetDisplayText()); // Setting a different whitespace elision must trigger a relayout. render_text->SetWhitespaceElision(true); - EXPECT_EQ(WideToUTF16(L"a\u2026"), render_text->GetDisplayText()); + EXPECT_EQ(u"a\u2026", render_text->GetDisplayText()); } TEST_F(RenderTextTest, ElidedObscuredText) { auto expected_render_text = std::make_unique(); expected_render_text->SetDisplayRect(Rect(0, 0, 9999, 100)); - const base::char16 elided_obscured_text[] = { - RenderText::kPasswordReplacementChar, - RenderText::kPasswordReplacementChar, kEllipsisUTF16[0], 0}; + const char16_t elided_obscured_text[] = {RenderText::kPasswordReplacementChar, + RenderText::kPasswordReplacementChar, + kEllipsisUTF16[0], 0}; expected_render_text->SetText(elided_obscured_text); RenderText* render_text = GetRenderText(); @@ -2324,17 +2324,17 @@ TEST_F(RenderTextTest, ElidedObscuredText) { render_text->SetDisplayRect( Rect(0, 0, expected_render_text->GetContentWidth(), 100)); render_text->SetObscured(true); - render_text->SetText(ASCIIToUTF16("abcdef")); - EXPECT_EQ(ASCIIToUTF16("abcdef"), render_text->text()); + render_text->SetText(u"abcdef"); + EXPECT_EQ(u"abcdef", render_text->text()); EXPECT_EQ(elided_obscured_text, render_text->GetDisplayText()); } TEST_F(RenderTextTest, MultilineElide) { RenderText* render_text = GetRenderText(); - base::string16 input_text; + std::u16string input_text; // Aim for 3 lines of text. for (int i = 0; i < 20; ++i) - input_text.append(ASCIIToUTF16("hello world ")); + input_text.append(u"hello world "); render_text->SetText(input_text); // Apply a style that tweaks the layout to make sure elision is calculated // with these styles. This can expose a behavior in layout where text is @@ -2352,7 +2352,7 @@ TEST_F(RenderTextTest, MultilineElide) { render_text->GetStringSize(); EXPECT_EQ(input_text, render_text->GetDisplayText()); - base::string16 actual_text; + std::u16string actual_text; // Try widening the space gradually, one pixel at a time, trying // to trigger a failure in layout. There was an issue where, right at // the edge of a word getting truncated, the estimate would be wrong @@ -2364,7 +2364,7 @@ TEST_F(RenderTextTest, MultilineElide) { actual_text = render_text->GetDisplayText(); EXPECT_LT(actual_text.size(), input_text.size()); EXPECT_EQ(actual_text, input_text.substr(0, actual_text.size() - 1) + - base::string16(kEllipsisUTF16)); + std::u16string(kEllipsisUTF16)); EXPECT_EQ(3U, render_text->GetNumLines()); } // Now remove line restriction. @@ -2377,14 +2377,14 @@ TEST_F(RenderTextTest, MultilineElide) { render_text->GetStringSize(); EXPECT_LT(actual_text.size(), input_text.size()); EXPECT_EQ(actual_text, input_text.substr(0, actual_text.size() - 1) + - base::string16(kEllipsisUTF16)); + std::u16string(kEllipsisUTF16)); } TEST_F(RenderTextTest, MultilineElideWrap) { RenderText* render_text = GetRenderText(); - base::string16 input_text; + std::u16string input_text; for (int i = 0; i < 20; ++i) - input_text.append(ASCIIToUTF16("hello world ")); + input_text.append(u"hello world "); render_text->SetText(input_text); render_text->SetMultiline(true); render_text->SetMaxLines(3); @@ -2398,10 +2398,10 @@ TEST_F(RenderTextTest, MultilineElideWrap) { for (auto wrap_behavior : wrap_behaviors) { render_text->SetWordWrapBehavior(wrap_behavior); render_text->GetStringSize(); - base::string16 actual_text = render_text->GetDisplayText(); + std::u16string actual_text = render_text->GetDisplayText(); EXPECT_LE(actual_text.size(), input_text.size()); EXPECT_EQ(actual_text, input_text.substr(0, actual_text.size() - 1) + - base::string16(kEllipsisUTF16)); + std::u16string(kEllipsisUTF16)); EXPECT_LE(render_text->GetNumLines(), 3U); } } @@ -2412,9 +2412,9 @@ TEST_F(RenderTextTest, MultilineElideWrap) { // styles are applied. TEST_F(RenderTextTest, DISABLED_MultilineElideWrapWithStyle) { RenderText* render_text = GetRenderText(); - base::string16 input_text; + std::u16string input_text; for (int i = 0; i < 20; ++i) - input_text.append(ASCIIToUTF16("hello world ")); + input_text.append(u"hello world "); render_text->SetText(input_text); render_text->ApplyWeight(Font::Weight::BOLD, Range(1, 20)); render_text->ApplyStyle(TEXT_STYLE_ITALIC, true, Range(1, 20)); @@ -2430,19 +2430,19 @@ TEST_F(RenderTextTest, DISABLED_MultilineElideWrapWithStyle) { for (auto wrap_behavior : wrap_behaviors) { render_text->SetWordWrapBehavior(wrap_behavior); render_text->GetStringSize(); - base::string16 actual_text = render_text->GetDisplayText(); + std::u16string actual_text = render_text->GetDisplayText(); EXPECT_LE(actual_text.size(), input_text.size()); EXPECT_EQ(actual_text, input_text.substr(0, actual_text.size() - 1) + - base::string16(kEllipsisUTF16)); + std::u16string(kEllipsisUTF16)); EXPECT_LE(render_text->GetNumLines(), 3U); } } TEST_F(RenderTextTest, MultilineElideWrapStress) { RenderText* render_text = GetRenderText(); - base::string16 input_text; + std::u16string input_text; for (int i = 0; i < 20; ++i) - input_text.append(ASCIIToUTF16("hello world ")); + input_text.append(u"hello world "); render_text->SetText(input_text); render_text->SetMultiline(true); render_text->SetMaxLines(3); @@ -2461,7 +2461,7 @@ TEST_F(RenderTextTest, MultilineElideWrapStress) { render_text->SetDisplayRect(Rect(i, 0)); render_text->SetWordWrapBehavior(wrap_behavior); render_text->GetStringSize(); - base::string16 actual_text = render_text->GetDisplayText(); + std::u16string actual_text = render_text->GetDisplayText(); EXPECT_LE(actual_text.size(), input_text.size()); EXPECT_LE(render_text->GetNumLines(), 3U); } @@ -2474,9 +2474,9 @@ TEST_F(RenderTextTest, MultilineElideWrapStress) { // styles are applied. TEST_F(RenderTextTest, DISABLED_MultilineElideWrapStressWithStyle) { RenderText* render_text = GetRenderText(); - base::string16 input_text; + std::u16string input_text; for (int i = 0; i < 20; ++i) - input_text.append(ASCIIToUTF16("hello world ")); + input_text.append(u"hello world "); render_text->SetText(input_text); render_text->ApplyWeight(Font::Weight::BOLD, Range(1, 20)); render_text->SetMultiline(true); @@ -2496,7 +2496,7 @@ TEST_F(RenderTextTest, DISABLED_MultilineElideWrapStressWithStyle) { render_text->SetDisplayRect(Rect(i, 0)); render_text->SetWordWrapBehavior(wrap_behavior); render_text->GetStringSize(); - base::string16 actual_text = render_text->GetDisplayText(); + std::u16string actual_text = render_text->GetDisplayText(); EXPECT_LE(actual_text.size(), input_text.size()); EXPECT_LE(render_text->GetNumLines(), 3U); } @@ -2507,7 +2507,7 @@ TEST_F(RenderTextTest, MultilineElideRTL) { RenderText* render_text = GetRenderText(); SetGlyphWidth(5); - base::string16 input_text(UTF8ToUTF16("זהו המסר של ההודעה")); + std::u16string input_text(u"זהו המסר של ההודעה"); render_text->SetText(input_text); render_text->SetCursorEnabled(false); render_text->SetMultiline(true); @@ -2517,7 +2517,7 @@ TEST_F(RenderTextTest, MultilineElideRTL) { render_text->GetStringSize(); EXPECT_EQ(render_text->GetDisplayText(), - input_text.substr(0, 8) + base::string16(kEllipsisUTF16)); + input_text.substr(0, 8) + std::u16string(kEllipsisUTF16)); EXPECT_EQ(render_text->GetNumLines(), 1U); } @@ -2525,7 +2525,7 @@ TEST_F(RenderTextTest, MultilineElideBiDi) { RenderText* render_text = GetRenderText(); SetGlyphWidth(5); - base::string16 input_text(UTF8ToUTF16("אa\nbcdבגדהefg\nhו")); + std::u16string input_text(UTF8ToUTF16("אa\nbcdבגדהefg\nhו")); render_text->SetText(input_text); render_text->SetCursorEnabled(false); render_text->SetMultiline(true); @@ -2535,7 +2535,7 @@ TEST_F(RenderTextTest, MultilineElideBiDi) { test_api()->EnsureLayout(); EXPECT_EQ(render_text->GetDisplayText(), - UTF8ToUTF16("אa\nbcdבג") + base::string16(kEllipsisUTF16)); + UTF8ToUTF16("אa\nbcdבג") + std::u16string(kEllipsisUTF16)); EXPECT_EQ(render_text->GetNumLines(), 2U); } @@ -2543,7 +2543,7 @@ TEST_F(RenderTextTest, MultilineElideLinebreak) { RenderText* render_text = GetRenderText(); SetGlyphWidth(5); - base::string16 input_text(ASCIIToUTF16("hello\nworld")); + std::u16string input_text(u"hello\nworld"); render_text->SetText(input_text); render_text->SetCursorEnabled(false); render_text->SetMultiline(true); @@ -2553,7 +2553,7 @@ TEST_F(RenderTextTest, MultilineElideLinebreak) { render_text->GetStringSize(); EXPECT_EQ(render_text->GetDisplayText(), - input_text.substr(0, 5) + base::string16(kEllipsisUTF16)); + input_text.substr(0, 5) + std::u16string(kEllipsisUTF16)); EXPECT_EQ(render_text->GetNumLines(), 1U); } @@ -2574,7 +2574,7 @@ TEST_F(RenderTextTest, ElidedStyledTextRtl) { for (const auto* raw_text : kInputTexts) { SCOPED_TRACE( base::StringPrintf("ElidedStyledTextRtl text = %s", raw_text)); - base::string16 input_text(UTF8ToUTF16(raw_text)); + std::u16string input_text(UTF8ToUTF16(raw_text)); RenderText* render_text = GetRenderText(); render_text->SetText(input_text); @@ -2587,7 +2587,7 @@ TEST_F(RenderTextTest, ElidedStyledTextRtl) { SCOPED_TRACE(base::StringPrintf("ElidedStyledTextRtl width = %d", i)); render_text->SetDisplayRect(Rect(i, 20)); render_text->GetStringSize(); - base::string16 display_text = render_text->GetDisplayText(); + std::u16string display_text = render_text->GetDisplayText(); EXPECT_LE(display_text.size(), input_text.size()); // Every size of content width was tried. @@ -2599,11 +2599,10 @@ TEST_F(RenderTextTest, ElidedStyledTextRtl) { TEST_F(RenderTextTest, ElidedEmail) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("test@example.com")); + render_text->SetText(u"test@example.com"); const Size size = render_text->GetStringSize(); - const base::string16 long_email = - ASCIIToUTF16("longemailaddresstest@example.com"); + const std::u16string long_email = u"longemailaddresstest@example.com"; render_text->SetText(long_email); render_text->SetElideBehavior(ELIDE_EMAIL); render_text->SetDisplayRect(Rect(size)); @@ -2676,8 +2675,8 @@ TEST_F(RenderTextTest, TruncatedObscuredText) { RenderText* render_text = GetRenderText(); render_text->set_truncate_length(3); render_text->SetObscured(true); - render_text->SetText(ASCIIToUTF16("abcdef")); - EXPECT_EQ(ASCIIToUTF16("abcdef"), render_text->text()); + render_text->SetText(u"abcdef"); + EXPECT_EQ(u"abcdef", render_text->text()); EXPECT_EQ(GetObscuredString(3, 2, kEllipsisUTF16[0]), render_text->GetDisplayText()); } @@ -2685,8 +2684,7 @@ TEST_F(RenderTextTest, TruncatedObscuredText) { TEST_F(RenderTextTest, TruncatedObscuredTextWithGraphemes) { RenderText* render_text = GetRenderText(); render_text->set_truncate_length(3); - render_text->SetText( - WideToUTF16(L"e\u0301\U0001F468\u200D\u2708\uFE0F\U0001D11E")); + render_text->SetText(u"e\u0301\U0001F468\u200D\u2708\uFE0F\U0001D11E"); render_text->SetObscured(true); EXPECT_EQ(GetObscuredString(3), render_text->GetDisplayText()); @@ -2703,7 +2701,7 @@ TEST_F(RenderTextTest, TruncatedObscuredTextWithGraphemes) { TEST_F(RenderTextTest, TruncatedCursorMovementLTR) { RenderText* render_text = GetRenderText(); render_text->set_truncate_length(2); - render_text->SetText(ASCIIToUTF16("abcd")); + render_text->SetText(u"abcd"); EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, SELECTION_NONE); @@ -2758,7 +2756,7 @@ TEST_F(RenderTextTest, TruncatedCursorMovementRTL) { TEST_F(RenderTextTest, MoveCursor_Character) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("123 456 789")); + render_text->SetText(u"123 456 789"); std::vector expected; // SELECTION_NONE. @@ -2821,7 +2819,7 @@ TEST_F(RenderTextTest, MoveCursor_Character) { TEST_F(RenderTextTest, MoveCursor_Word) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("123 456 789")); + render_text->SetText(u"123 456 789"); std::vector expected; // SELECTION_NONE. @@ -2916,7 +2914,7 @@ TEST_F(RenderTextTest, MoveCursor_Word) { TEST_F(RenderTextTest, MoveCursor_Word_RTL) { RenderText* render_text = GetRenderText(); - render_text->SetText(UTF8ToUTF16("אבג דהו זחט")); + render_text->SetText(u"אבג דהו זחט"); std::vector expected; // SELECTION_NONE. @@ -3011,7 +3009,7 @@ TEST_F(RenderTextTest, MoveCursor_Word_RTL) { TEST_F(RenderTextTest, MoveCursor_Line) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("123 456 789")); + render_text->SetText(u"123 456 789"); std::vector expected; for (auto break_type : {LINE_BREAK, FIELD_BREAK}) { @@ -3143,7 +3141,7 @@ TEST_F(RenderTextTest, MoveCursor_UpDown) { TEST_F(RenderTextTest, MoveCursor_UpDown_Newline) { SetGlyphWidth(5); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("123 456\n123 456 ")); + render_text->SetText(u"123 456\n123 456 "); render_text->SetDisplayRect(Rect(100, 1000)); render_text->SetMultiline(true); EXPECT_EQ(2U, render_text->GetNumLines()); @@ -3189,7 +3187,7 @@ TEST_F(RenderTextTest, MoveCursor_UpDown_Newline) { TEST_F(RenderTextTest, MoveCursor_UpDown_Cache) { SetGlyphWidth(5); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("123 456\n\n123 456")); + render_text->SetText(u"123 456\n\n123 456"); render_text->SetDisplayRect(Rect(45, 1000)); render_text->SetMultiline(true); EXPECT_EQ(3U, render_text->GetNumLines()); @@ -3230,7 +3228,7 @@ TEST_F(RenderTextTest, MoveCursor_UpDown_Cache) { TEST_F(RenderTextTest, MoveCursorWithNewline) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("a\r\nb")); + render_text->SetText(u"a\r\nb"); render_text->SetMultiline(false); EXPECT_EQ(1U, render_text->GetNumLines()); @@ -3251,7 +3249,7 @@ TEST_F(RenderTextTest, GetTextDirectionInvalidation) { const base::i18n::TextDirection original_text_direction = render_text->GetTextDirection(); - render_text->SetText(ASCIIToUTF16("a")); + render_text->SetText(u"a"); EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); render_text->SetText(UTF8ToUTF16("\u05d0")); @@ -3260,7 +3258,7 @@ TEST_F(RenderTextTest, GetTextDirectionInvalidation) { // The codepoints u+2026 (ellipsis) has no strong direction. render_text->SetText(UTF8ToUTF16("\u2026")); EXPECT_EQ(original_text_direction, render_text->GetTextDirection()); - render_text->AppendText(ASCIIToUTF16("a")); + render_text->AppendText(u"a"); EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); render_text->SetText(UTF8ToUTF16("\u2026")); @@ -3276,7 +3274,7 @@ TEST_F(RenderTextTest, GetDisplayTextDirectionInvalidation) { const base::i18n::TextDirection original_text_direction = render_text->GetDisplayTextDirection(); - render_text->SetText(ASCIIToUTF16("a")); + render_text->SetText(u"a"); EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetDisplayTextDirection()); render_text->SetText(UTF8ToUTF16("\u05d0")); @@ -3285,7 +3283,7 @@ TEST_F(RenderTextTest, GetDisplayTextDirectionInvalidation) { // The codepoints u+2026 (ellipsis) has no strong direction. render_text->SetText(UTF8ToUTF16("\u2026")); EXPECT_EQ(original_text_direction, render_text->GetDisplayTextDirection()); - render_text->AppendText(ASCIIToUTF16("a")); + render_text->AppendText(u"a"); EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetDisplayTextDirection()); render_text->SetText(UTF8ToUTF16("\u2026")); @@ -3531,7 +3529,7 @@ INSTANTIATE_TEST_SUITE_P( TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) { RenderText* render_text = GetRenderText(); // Pure LTR. - render_text->SetText(ASCIIToUTF16("abc")); + render_text->SetText(u"abc"); // |expected| saves the expected SelectionModel when moving cursor from left // to right. std::vector expected; @@ -3698,7 +3696,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRight_MeiryoUILigatures) { // Meiryo UI uses single-glyph ligatures for 'ff' and 'ffi', but each letter // (code point) has unique bounds, so mid-glyph cursoring should be possible. render_text->SetFontList(FontList("Meiryo UI, 12px")); - render_text->SetText(ASCIIToUTF16("ff ffi")); + render_text->SetText(u"ff ffi"); render_text->SetDisplayRect(gfx::Rect(100, 100)); EXPECT_EQ(0U, render_text->cursor_position()); @@ -3778,7 +3776,7 @@ TEST_F(RenderTextTest, GraphemeIterator) { iterator = render_text->GetGraphemeIteratorAtDisplayTextIndex(2); EXPECT_EQ(2U, render_text->GetTextIndex(iterator)); - render_text->SetText(WideToUTF16(L"a\U0001F601b")); + render_text->SetText(u"a\U0001F601b"); render_text->SetObscured(true); iterator = render_text->GetGraphemeIteratorAtDisplayTextIndex(0); EXPECT_EQ(0U, render_text->GetTextIndex(iterator)); @@ -3811,13 +3809,13 @@ TEST_F(RenderTextTest, GraphemeIterator) { } TEST_F(RenderTextTest, GraphemeBoundaries) { - static const wchar_t text[] = - L"\u0065\u0301" // Letter 'e' U+0065 and acute accent U+0301 - L"\u0036\uFE0F\u20E3" // Emoji 'keycap letter 6' - L"\U0001F468\u200D\u2708\uFE0F"; // Emoji 'pilot'. + static const char16_t text[] = + u"\u0065\u0301" // Letter 'e' U+0065 and acute accent U+0301 + u"\u0036\uFE0F\u20E3" // Emoji 'keycap letter 6' + u"\U0001F468\u200D\u2708\uFE0F"; // Emoji 'pilot'. RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(text)); + render_text->SetText(text); EXPECT_TRUE(render_text->IsGraphemeBoundary(0)); EXPECT_FALSE(render_text->IsGraphemeBoundary(1)); @@ -3858,52 +3856,52 @@ TEST_F(RenderTextTest, GraphemeBoundaries) { TEST_F(RenderTextTest, GraphemePositions) { // LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR abc, and LTR कि. - const base::string16 kText1 = UTF8ToUTF16("\u0915\u093fabc\u0915\u093f"); + const std::u16string kText1 = UTF8ToUTF16("\u0915\u093fabc\u0915\u093f"); // LTR ab, LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR cd. - const base::string16 kText2 = UTF8ToUTF16("ab\u0915\u093fcd"); + const std::u16string kText2 = UTF8ToUTF16("ab\u0915\u093fcd"); // LTR ab, 𝄞 'MUSICAL SYMBOL G CLEF' U+1D11E (surrogate pair), LTR cd. // Windows requires wide strings for \Unnnnnnnn universal character names. - const base::string16 kText3 = WideToUTF16(L"ab\U0001D11Ecd"); + const std::u16string kText3 = u"ab\U0001D11Ecd"; struct { - base::string16 text; + std::u16string text; size_t index; size_t expected_previous; size_t expected_next; } cases[] = { - { base::string16(), 0, 0, 0 }, - { base::string16(), 1, 0, 0 }, - { base::string16(), 50, 0, 0 }, - { kText1, 0, 0, 2 }, - { kText1, 1, 0, 2 }, - { kText1, 2, 0, 3 }, - { kText1, 3, 2, 4 }, - { kText1, 4, 3, 5 }, - { kText1, 5, 4, 7 }, - { kText1, 6, 5, 7 }, - { kText1, 7, 5, 7 }, - { kText1, 8, 7, 7 }, - { kText1, 50, 7, 7 }, - { kText2, 0, 0, 1 }, - { kText2, 1, 0, 2 }, - { kText2, 2, 1, 4 }, - { kText2, 3, 2, 4 }, - { kText2, 4, 2, 5 }, - { kText2, 5, 4, 6 }, - { kText2, 6, 5, 6 }, - { kText2, 7, 6, 6 }, - { kText2, 50, 6, 6 }, - { kText3, 0, 0, 1 }, - { kText3, 1, 0, 2 }, - { kText3, 2, 1, 4 }, - { kText3, 3, 2, 4 }, - { kText3, 4, 2, 5 }, - { kText3, 5, 4, 6 }, - { kText3, 6, 5, 6 }, - { kText3, 7, 6, 6 }, - { kText3, 50, 6, 6 }, + {std::u16string(), 0, 0, 0}, + {std::u16string(), 1, 0, 0}, + {std::u16string(), 50, 0, 0}, + {kText1, 0, 0, 2}, + {kText1, 1, 0, 2}, + {kText1, 2, 0, 3}, + {kText1, 3, 2, 4}, + {kText1, 4, 3, 5}, + {kText1, 5, 4, 7}, + {kText1, 6, 5, 7}, + {kText1, 7, 5, 7}, + {kText1, 8, 7, 7}, + {kText1, 50, 7, 7}, + {kText2, 0, 0, 1}, + {kText2, 1, 0, 2}, + {kText2, 2, 1, 4}, + {kText2, 3, 2, 4}, + {kText2, 4, 2, 5}, + {kText2, 5, 4, 6}, + {kText2, 6, 5, 6}, + {kText2, 7, 6, 6}, + {kText2, 50, 6, 6}, + {kText3, 0, 0, 1}, + {kText3, 1, 0, 2}, + {kText3, 2, 1, 4}, + {kText3, 3, 2, 4}, + {kText3, 4, 2, 5}, + {kText3, 5, 4, 6}, + {kText3, 6, 5, 6}, + {kText3, 7, 6, 6}, + {kText3, 50, 6, 6}, }; RenderText* render_text = GetRenderText(); @@ -3925,9 +3923,9 @@ TEST_F(RenderTextTest, GraphemePositions) { TEST_F(RenderTextTest, MidGraphemeSelectionBounds) { // Test that selection bounds may be set amid multi-character graphemes. - const base::string16 kHindi = UTF8ToUTF16("\u0915\u093f"); - const base::string16 kThai = UTF8ToUTF16("\u0e08\u0e33"); - const base::string16 cases[] = { kHindi, kThai }; + const std::u16string kHindi = UTF8ToUTF16("\u0915\u093f"); + const std::u16string kThai = UTF8ToUTF16("\u0e08\u0e33"); + const std::u16string cases[] = {kHindi, kThai}; RenderText* render_text = GetRenderText(); render_text->SetDisplayRect(Rect(100, 1000)); @@ -4011,7 +4009,7 @@ TEST_F(RenderTextTest, FindCursorPositionMultiline) { // boundaries. TEST_F(RenderTextTest, FindCursorPosition_GraphemeBoundaries) { struct { - base::string16 text; + std::u16string text; std::set expected_cursor_positions; } cases[] = { // LTR कि (DEVANAGARI KA with VOWEL I) (2-char grapheme), LTR abc, LTR कि. @@ -4020,7 +4018,7 @@ TEST_F(RenderTextTest, FindCursorPosition_GraphemeBoundaries) { {UTF8ToUTF16("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. - {WideToUTF16(L"ab\U0001D11Ecd"), {0, 1, 2, 4, 5, 6}}}; + {u"ab\U0001D11Ecd", {0, 1, 2, 4, 5, 6}}}; RenderText* render_text = GetRenderText(); render_text->SetDisplayRect(gfx::Rect(100, 30)); @@ -4038,26 +4036,26 @@ TEST_F(RenderTextTest, FindCursorPosition_GraphemeBoundaries) { TEST_F(RenderTextTest, EdgeSelectionModels) { // Simple Latin text. - const base::string16 kLatin = ASCIIToUTF16("abc"); + const std::u16string kLatin = u"abc"; // LTR कि (DEVANAGARI KA with VOWEL I). - const base::string16 kLTRGrapheme = UTF8ToUTF16("\u0915\u093f"); + const std::u16string kLTRGrapheme = UTF8ToUTF16("\u0915\u093f"); // LTR कि (DEVANAGARI KA with VOWEL I), LTR a, LTR कि. - const base::string16 kHindiLatin = UTF8ToUTF16("\u0915\u093fa\u0915\u093f"); + const std::u16string kHindiLatin = UTF8ToUTF16("\u0915\u093fa\u0915\u093f"); // RTL נָ (Hebrew letter NUN and point QAMATS). - const base::string16 kRTLGrapheme = UTF8ToUTF16("\u05e0\u05b8"); + const std::u16string kRTLGrapheme = UTF8ToUTF16("\u05e0\u05b8"); // RTL נָ (Hebrew letter NUN and point QAMATS), LTR a, RTL נָ. - const base::string16 kHebrewLatin = UTF8ToUTF16("\u05e0\u05b8a\u05e0\u05b8"); + const std::u16string kHebrewLatin = UTF8ToUTF16("\u05e0\u05b8a\u05e0\u05b8"); struct { - base::string16 text; + std::u16string text; base::i18n::TextDirection expected_text_direction; } cases[] = { - { base::string16(), base::i18n::LEFT_TO_RIGHT }, - { kLatin, base::i18n::LEFT_TO_RIGHT }, - { kLTRGrapheme, base::i18n::LEFT_TO_RIGHT }, - { kHindiLatin, base::i18n::LEFT_TO_RIGHT }, - { kRTLGrapheme, base::i18n::RIGHT_TO_LEFT }, - { kHebrewLatin, base::i18n::RIGHT_TO_LEFT }, + {std::u16string(), base::i18n::LEFT_TO_RIGHT}, + {kLatin, base::i18n::LEFT_TO_RIGHT}, + {kLTRGrapheme, base::i18n::LEFT_TO_RIGHT}, + {kHindiLatin, base::i18n::LEFT_TO_RIGHT}, + {kRTLGrapheme, base::i18n::RIGHT_TO_LEFT}, + {kHebrewLatin, base::i18n::RIGHT_TO_LEFT}, }; RenderText* render_text = GetRenderText(); @@ -4089,7 +4087,7 @@ TEST_F(RenderTextTest, SelectAll) { for (size_t i = 0; i < 2; ++i) { SetRTL(!base::i18n::IsRTL()); // Test that an empty string produces an empty selection model. - render_text->SetText(base::string16()); + render_text->SetText(std::u16string()); EXPECT_EQ(render_text->selection_model(), SelectionModel()); // Test the weak, LTR, RTL, and Bidi string cases. @@ -4150,7 +4148,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection_Multiline) { RenderText* render_text = GetRenderText(); render_text->SetMultiline(true); render_text->SetDisplayRect(Rect(20, 1000)); - render_text->SetText(ASCIIToUTF16("012 456\n\n90")); + render_text->SetText(u"012 456\n\n90"); EXPECT_EQ(4U, render_text->GetNumLines()); // Move cursor right to the end of the text. @@ -4237,7 +4235,7 @@ TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection_Multiline) { TEST_F(RenderTextTest, CenteredDisplayOffset) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefghij")); + render_text->SetText(u"abcdefghij"); render_text->SetHorizontalAlignment(ALIGN_CENTER); const int kEnlargement = 10; @@ -4273,7 +4271,7 @@ TEST_F(RenderTextTest, CenteredDisplayOffset) { void MoveLeftRightByWordVerifier(RenderText* render_text, const char* str) { SCOPED_TRACE(str); - const base::string16 str16(UTF8ToUTF16(str)); + const std::u16string str16(UTF8ToUTF16(str)); render_text->SetText(str16); // Test moving by word from left to right. @@ -4416,7 +4414,7 @@ TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) { TEST_F(RenderTextTest, MoveLeftRightByWordInTextWithMultiSpaces) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abc def")); + render_text->SetText(u"abc def"); render_text->SetCursorPosition(5); render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, SELECTION_NONE); #if defined(OS_WIN) @@ -4433,7 +4431,7 @@ TEST_F(RenderTextTest, MoveLeftRightByWordInTextWithMultiSpaces) { TEST_F(RenderTextTest, MoveLeftRightByWordInThaiText) { RenderText* render_text = GetRenderText(); // เรียกดูรวดเร็ว is broken to เรียก|ดู|รวดเร็ว. - render_text->SetText(UTF8ToUTF16("เรียกดูรวดเร็ว")); + render_text->SetText(u"เรียกดูรวดเร็ว"); 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); @@ -4494,19 +4492,19 @@ TEST_F(RenderTextTest, MoveLeftRightByWordInChineseText) { TEST_F(RenderTextTest, DirectedSelections) { RenderText* render_text = GetRenderText(); - auto ResultAfter = [&](VisualCursorDirection direction) -> base::string16 { + auto ResultAfter = [&](VisualCursorDirection direction) -> std::u16string { render_text->MoveCursor(CHARACTER_BREAK, direction, SELECTION_RETAIN); return GetSelectedText(render_text); }; - render_text->SetText(ASCIIToUTF16("01234")); + render_text->SetText(u"01234"); // Test Right, then Left. LTR. // Undirected, or forward when kSelectionIsAlwaysDirected. render_text->SelectRange({2, 4}); - EXPECT_EQ(ASCIIToUTF16("23"), GetSelectedText(render_text)); - EXPECT_EQ(ASCIIToUTF16("234"), ResultAfter(CURSOR_RIGHT)); - EXPECT_EQ(ASCIIToUTF16("23"), ResultAfter(CURSOR_LEFT)); + EXPECT_EQ(u"23", GetSelectedText(render_text)); + EXPECT_EQ(u"234", ResultAfter(CURSOR_RIGHT)); + EXPECT_EQ(u"23", ResultAfter(CURSOR_LEFT)); // Test collapsing the selection. This always ignores any existing direction. render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, SELECTION_NONE); @@ -4514,12 +4512,12 @@ TEST_F(RenderTextTest, DirectedSelections) { // Undirected, or backward when kSelectionIsAlwaysDirected. render_text->SelectRange({4, 2}); - EXPECT_EQ(ASCIIToUTF16("23"), GetSelectedText(render_text)); + EXPECT_EQ(u"23", GetSelectedText(render_text)); if (RenderText::kSelectionIsAlwaysDirected) - EXPECT_EQ(ASCIIToUTF16("3"), ResultAfter(CURSOR_RIGHT)); // Keep left. + EXPECT_EQ(u"3", ResultAfter(CURSOR_RIGHT)); // Keep left. else - EXPECT_EQ(ASCIIToUTF16("234"), ResultAfter(CURSOR_RIGHT)); // Pick right. - EXPECT_EQ(ASCIIToUTF16("23"), ResultAfter(CURSOR_LEFT)); + EXPECT_EQ(u"234", ResultAfter(CURSOR_RIGHT)); // Pick right. + EXPECT_EQ(u"23", ResultAfter(CURSOR_LEFT)); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, SELECTION_NONE); EXPECT_EQ(Range(2, 2), render_text->selection()); // Collapse left. @@ -4527,30 +4525,30 @@ TEST_F(RenderTextTest, DirectedSelections) { // Test Left, then Right. LTR. // Undirected, or forward when kSelectionIsAlwaysDirected. render_text->SelectRange({2, 4}); - EXPECT_EQ(ASCIIToUTF16("23"), GetSelectedText(render_text)); // Sanity check, + EXPECT_EQ(u"23", GetSelectedText(render_text)); // Sanity check, if (RenderText::kSelectionIsAlwaysDirected) - EXPECT_EQ(ASCIIToUTF16("2"), ResultAfter(CURSOR_LEFT)); // Keep right. + EXPECT_EQ(u"2", ResultAfter(CURSOR_LEFT)); // Keep right. else - EXPECT_EQ(ASCIIToUTF16("123"), ResultAfter(CURSOR_LEFT)); // Pick left. - EXPECT_EQ(ASCIIToUTF16("23"), ResultAfter(CURSOR_RIGHT)); + EXPECT_EQ(u"123", ResultAfter(CURSOR_LEFT)); // Pick left. + EXPECT_EQ(u"23", ResultAfter(CURSOR_RIGHT)); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, SELECTION_NONE); EXPECT_EQ(Range(4, 4), render_text->selection()); // Collapse right. // Undirected, or backward when kSelectionIsAlwaysDirected. render_text->SelectRange({4, 2}); - EXPECT_EQ(ASCIIToUTF16("23"), GetSelectedText(render_text)); - EXPECT_EQ(ASCIIToUTF16("123"), ResultAfter(CURSOR_LEFT)); - EXPECT_EQ(ASCIIToUTF16("23"), ResultAfter(CURSOR_RIGHT)); + EXPECT_EQ(u"23", GetSelectedText(render_text)); + EXPECT_EQ(u"123", ResultAfter(CURSOR_LEFT)); + EXPECT_EQ(u"23", ResultAfter(CURSOR_RIGHT)); render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, SELECTION_NONE); EXPECT_EQ(Range(4, 4), render_text->selection()); // Collapse right. - auto ToHebrew = [](const char* digits) -> base::string16 { - const base::string16 hebrew = UTF8ToUTF16("אבגדח"); // Roughly "abcde". + auto ToHebrew = [](const char* digits) -> std::u16string { + const std::u16string hebrew = u"אבגדח"; // Roughly "abcde". DCHECK_EQ(5u, hebrew.size()); - base::string16 result; + std::u16string result; for (const char* d = digits; *d; d++) result += hebrew[*d - '0']; return result; @@ -4611,7 +4609,7 @@ TEST_F(RenderTextTest, DirectedSelections_Multiline) { return GetSelectedText(render_text); }; - render_text->SetText(ASCIIToUTF16("01234\n56789\nabcde")); + render_text->SetText(u"01234\n56789\nabcde"); render_text->SetMultiline(true); render_text->SetDisplayRect(Rect(500, 500)); ResetCursorX(); @@ -4619,9 +4617,9 @@ TEST_F(RenderTextTest, DirectedSelections_Multiline) { // Test Down, then Up. LTR. // Undirected, or forward when kSelectionIsAlwaysDirected. render_text->SelectRange({2, 4}); - EXPECT_EQ(ASCIIToUTF16("23"), GetSelectedText(render_text)); - EXPECT_EQ(ASCIIToUTF16("234\n5678"), ResultAfter(CURSOR_DOWN)); - EXPECT_EQ(ASCIIToUTF16("23"), ResultAfter(CURSOR_UP)); + EXPECT_EQ(u"23", GetSelectedText(render_text)); + EXPECT_EQ(u"234\n5678", ResultAfter(CURSOR_DOWN)); + EXPECT_EQ(u"23", ResultAfter(CURSOR_UP)); // Test collapsing the selection. This always ignores any existing direction. render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, SELECTION_NONE); @@ -4630,40 +4628,40 @@ TEST_F(RenderTextTest, DirectedSelections_Multiline) { // Undirected, or backward when kSelectionIsAlwaysDirected. ResetCursorX(); // Reset cached cursor x position. render_text->SelectRange({4, 2}); - EXPECT_EQ(ASCIIToUTF16("23"), GetSelectedText(render_text)); + EXPECT_EQ(u"23", GetSelectedText(render_text)); if (RenderText::kSelectionIsAlwaysDirected) { - EXPECT_EQ(ASCIIToUTF16("4\n56"), ResultAfter(CURSOR_DOWN)); // Keep left. + EXPECT_EQ(u"4\n56", ResultAfter(CURSOR_DOWN)); // Keep left. } else { - EXPECT_EQ(ASCIIToUTF16("234\n5678"), + EXPECT_EQ(u"234\n5678", ResultAfter(CURSOR_DOWN)); // Pick right. } - EXPECT_EQ(ASCIIToUTF16("23"), ResultAfter(CURSOR_UP)); + EXPECT_EQ(u"23", ResultAfter(CURSOR_UP)); // Test with multi-line selection. // Undirected, or forward when kSelectionIsAlwaysDirected. ResetCursorX(); render_text->SelectRange({2, 7}); // Select multi-line. - EXPECT_EQ(ASCIIToUTF16("234\n5"), GetSelectedText(render_text)); - EXPECT_EQ(ASCIIToUTF16("234\n56789\na"), ResultAfter(CURSOR_DOWN)); - EXPECT_EQ(ASCIIToUTF16("234\n5"), ResultAfter(CURSOR_UP)); + EXPECT_EQ(u"234\n5", GetSelectedText(render_text)); + EXPECT_EQ(u"234\n56789\na", ResultAfter(CURSOR_DOWN)); + EXPECT_EQ(u"234\n5", ResultAfter(CURSOR_UP)); // Undirected, or backward when kSelectionIsAlwaysDirected. ResetCursorX(); render_text->SelectRange({7, 2}); // Select multi-line. - EXPECT_EQ(ASCIIToUTF16("234\n5"), GetSelectedText(render_text)); + EXPECT_EQ(u"234\n5", GetSelectedText(render_text)); if (RenderText::kSelectionIsAlwaysDirected) { - EXPECT_EQ(ASCIIToUTF16("6"), ResultAfter(CURSOR_DOWN)); // Keep left. + EXPECT_EQ(u"6", ResultAfter(CURSOR_DOWN)); // Keep left. } else { - EXPECT_EQ(ASCIIToUTF16("234\n56789\na"), + EXPECT_EQ(u"234\n56789\na", ResultAfter(CURSOR_DOWN)); // Pick right. } - EXPECT_EQ(ASCIIToUTF16("234\n5"), ResultAfter(CURSOR_UP)); + EXPECT_EQ(u"234\n5", ResultAfter(CURSOR_UP)); } TEST_F(RenderTextTest, StringSizeSanity) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("Hello World")); + render_text->SetText(u"Hello World"); const Size string_size = render_text->GetStringSize(); EXPECT_GT(string_size.width(), 0); EXPECT_GT(string_size.height(), 0); @@ -4675,7 +4673,7 @@ TEST_F(RenderTextTest, StringSizeLongStrings) { render_text->set_truncate_length(0); Size previous_string_size; for (size_t length = 10; length < 1000000; length *= 10) { - render_text->SetText(base::string16(length, 'a')); + render_text->SetText(std::u16string(length, 'a')); const Size string_size = render_text->GetStringSize(); EXPECT_GT(string_size.width(), previous_string_size.width()); EXPECT_GT(string_size.height(), 0); @@ -4693,12 +4691,12 @@ TEST_F(RenderTextTest, StringSizeEmptyString) { // The empty string respects FontList metrics for non-zero height // and baseline. - render_text->SetText(base::string16()); + render_text->SetText(std::u16string()); EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height()); EXPECT_EQ(0, render_text->GetStringSize().width()); EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline()); - render_text->SetText(ASCIIToUTF16(" ")); + render_text->SetText(u" "); EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height()); EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline()); } @@ -4759,7 +4757,7 @@ TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) { TEST_F(RenderTextTest, StringSizeMultiline) { SetGlyphWidth(5); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("Hello\nWorld")); + render_text->SetText(u"Hello\nWorld"); const Size string_size = render_text->GetStringSize(); EXPECT_EQ(55, string_size.width()); @@ -4781,7 +4779,7 @@ TEST_F(RenderTextTest, StringSizeMultiline) { TEST_F(RenderTextTest, MinLineHeight) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("Hello!")); + render_text->SetText(u"Hello!"); SizeF default_size = render_text->GetStringSizeF(); ASSERT_NE(0, default_size.height()); ASSERT_NE(0, default_size.width()); @@ -4800,8 +4798,7 @@ TEST_F(RenderTextTest, MinLineHeight) { // recommended by gfx::Font. TEST_F(RenderTextTest, DefaultLineHeights) { RenderText* render_text = GetRenderText(); - render_text->SetText( - ASCIIToUTF16("A quick brown fox jumped over the lazy dog!")); + render_text->SetText(u"A quick brown fox jumped over the lazy dog!"); #if defined(OS_APPLE) const FontList body2_font = FontList().DeriveWithSizeDelta(-1); @@ -4881,7 +4878,7 @@ TEST_F(RenderTextTest, TextSizeMultiline) { for (size_t line = 0; line < 10; ++line) { if (line != 0) - render_text->AppendText(ASCIIToUTF16("\n")); + render_text->AppendText(u"\n"); const int text_length = line; render_text->AppendText(ASCIIToUTF16(std::string(text_length, 'x'))); @@ -4918,7 +4915,7 @@ TEST_F(RenderTextTest, LineSizeMultiline) { RenderText* render_text = GetRenderText(); render_text->SetMultiline(true); - render_text->SetText(ASCIIToUTF16("xx\nxxx\nxxxxx")); + render_text->SetText(u"xx\nxxx\nxxxxx"); const float expected_line1_size = 3 * kGlyphWidth; const float expected_line2_size = 4 * kGlyphWidth; @@ -4999,7 +4996,7 @@ TEST_F(RenderTextTest, StringSizeBoldWidth) { render_text->SetFontList(FontList("Arial, 20px")); #endif // defined(OS_FUCHSIA) - render_text->SetText(ASCIIToUTF16("Hello World")); + render_text->SetText(u"Hello World"); const int plain_width = render_text->GetStringSize().width(); EXPECT_GT(plain_width, 0); @@ -5023,8 +5020,8 @@ TEST_F(RenderTextTest, StringSizeBoldWidth) { } TEST_F(RenderTextTest, StringSizeHeight) { - base::string16 cases[] = { - ASCIIToUTF16("Hello World!"), // English + 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) @@ -5052,14 +5049,14 @@ TEST_F(RenderTextTest, StringSizeHeight) { TEST_F(RenderTextTest, GetBaselineSanity) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("Hello World")); + render_text->SetText(u"Hello World"); const int baseline = render_text->GetBaseline(); EXPECT_GT(baseline, 0); } TEST_F(RenderTextTest, GetCursorBoundsInReplacementMode) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefg")); + render_text->SetText(u"abcdefg"); render_text->SetDisplayRect(Rect(100, 17)); SelectionModel sel_b(1, CURSOR_FORWARD); SelectionModel sel_c(2, CURSOR_FORWARD); @@ -5077,8 +5074,7 @@ TEST_F(RenderTextTest, GetCursorBoundsWithGraphemes) { SetGlyphHeight(kGlyphHeight); RenderText* render_text = GetRenderText(); - render_text->SetText( - WideToUTF16(L"a\u0300e\u0301\U0001F601x\U0001F573\uFE0F")); + render_text->SetText(u"a\u0300e\u0301\U0001F601x\U0001F573\uFE0F"); render_text->SetDisplayRect(Rect(100, 20)); render_text->SetVerticalAlignment(ALIGN_TOP); @@ -5113,7 +5109,7 @@ TEST_F(RenderTextTest, GetTextOffset) { ResetRenderTextInstance(); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefg")); + render_text->SetText(u"abcdefg"); render_text->SetFontList(FontList("Arial, 13px")); // Set display area's size equal to the font size. @@ -5167,7 +5163,7 @@ TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) { ResetRenderTextInstance(); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefg")); + render_text->SetText(u"abcdefg"); render_text->SetFontList(FontList("Arial, 13px")); const int kEnlargement = 2; const Size font_size(render_text->GetContentWidth() + kEnlargement, @@ -5181,7 +5177,7 @@ TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) { TEST_F(RenderTextTest, GetTextOffsetVerticalAlignment) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefg")); + render_text->SetText(u"abcdefg"); render_text->SetFontList(FontList("Arial, 13px")); // Set display area's size equal to the font size. @@ -5219,7 +5215,7 @@ TEST_F(RenderTextTest, GetTextOffsetVerticalAlignment_Multiline) { RenderText* render_text = GetRenderText(); render_text->SetMultiline(true); render_text->SetMaxLines(2); - render_text->SetText(ASCIIToUTF16("abcdefg hijklmn")); + render_text->SetText(u"abcdefg hijklmn"); render_text->SetFontList(FontList("Arial, 13px")); // Set display area's size equal to the font size. @@ -5255,7 +5251,7 @@ TEST_F(RenderTextTest, GetTextOffsetVerticalAlignment_Multiline) { TEST_F(RenderTextTest, SetDisplayOffset) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefg")); + render_text->SetText(u"abcdefg"); render_text->SetFontList(FontList("Arial, 13px")); const Size font_size(render_text->GetContentWidth(), @@ -5329,20 +5325,20 @@ TEST_F(RenderTextTest, SetDisplayOffset) { TEST_F(RenderTextTest, SameFontForParentheses) { struct { - const base::char16 left_char; - const base::char16 right_char; + const char16_t left_char; + const char16_t right_char; } punctuation_pairs[] = { { '(', ')' }, { '{', '}' }, { '<', '>' }, }; struct { - base::string16 text; + std::u16string text; } cases[] = { // English(English) - {ASCIIToUTF16("Hello World(a)")}, + {u"Hello World(a)"}, // English(English)English - {ASCIIToUTF16("Hello World(a)Hello World")}, + {u"Hello World(a)Hello World"}, // Japanese(English) {UTF8ToUTF16("\u6328\u62f6(a)")}, @@ -5368,11 +5364,11 @@ TEST_F(RenderTextTest, SameFontForParentheses) { RenderText* render_text = GetRenderText(); for (size_t i = 0; i < base::size(cases); ++i) { - base::string16 text = cases[i].text; + std::u16string text = cases[i].text; const size_t start_paren_char_index = text.find('('); - ASSERT_NE(base::string16::npos, start_paren_char_index); + ASSERT_NE(std::u16string::npos, start_paren_char_index); const size_t end_paren_char_index = text.find(')'); - ASSERT_NE(base::string16::npos, end_paren_char_index); + ASSERT_NE(std::u16string::npos, end_paren_char_index); for (size_t j = 0; j < base::size(punctuation_pairs); ++j) { text[start_paren_char_index] = punctuation_pairs[j].left_char; @@ -5405,13 +5401,13 @@ TEST_F(RenderTextTest, SameFontForParentheses) { // caret is drawn at high DPI. crbug.com/164100. TEST_F(RenderTextTest, CaretWidth) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefg")); + render_text->SetText(u"abcdefg"); EXPECT_GE(render_text->GetUpdatedCursorBounds().width(), 1); } TEST_F(RenderTextTest, SelectWord) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16(" foo a.bc.d bar")); + render_text->SetText(u" foo a.bc.d bar"); struct { size_t cursor; @@ -5455,13 +5451,13 @@ TEST_F(RenderTextTest, LastWordSelected) { render_text->SetText(ASCIIToUTF16(kTestURL1)); render_text->SetCursorPosition(kTestURL1.length()); render_text->SelectWord(); - EXPECT_EQ(ASCIIToUTF16("com"), GetSelectedText(render_text)); + EXPECT_EQ(u"com", GetSelectedText(render_text)); EXPECT_FALSE(render_text->selection().is_reversed()); render_text->SetText(ASCIIToUTF16(kTestURL2)); render_text->SetCursorPosition(kTestURL2.length()); render_text->SelectWord(); - EXPECT_EQ(ASCIIToUTF16("/"), GetSelectedText(render_text)); + EXPECT_EQ(u"/", GetSelectedText(render_text)); EXPECT_FALSE(render_text->selection().is_reversed()); } @@ -5475,13 +5471,13 @@ TEST_F(RenderTextTest, SelectMultipleWords) { render_text->SetText(ASCIIToUTF16(kTestURL)); render_text->SelectRange(Range(16, 20)); render_text->SelectWord(); - EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text)); + EXPECT_EQ(u"google.com", GetSelectedText(render_text)); EXPECT_FALSE(render_text->selection().is_reversed()); // SelectWord should preserve the selection direction. render_text->SelectRange(Range(20, 16)); render_text->SelectWord(); - EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text)); + EXPECT_EQ(u"google.com", GetSelectedText(render_text)); EXPECT_TRUE(render_text->selection().is_reversed()); } @@ -5490,7 +5486,7 @@ TEST_F(RenderTextTest, DisplayRectShowsCursorLTR) { ASSERT_FALSE(base::i18n::ICUIsRTL()); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefghijklmnopqrstuvwxzyabcdefg")); + render_text->SetText(u"abcdefghijklmnopqrstuvwxzyabcdefg"); render_text->SetCursorPosition(render_text->text().length()); int width = render_text->GetStringSize().width(); ASSERT_GT(width, 10); @@ -5548,7 +5544,7 @@ TEST_F(RenderTextTest, DisplayRectShowsCursorRTL) { // Reset the render text instance since the locale was changed. ResetRenderTextInstance(); RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefghijklmnopqrstuvwxzyabcdefg")); + render_text->SetText(u"abcdefghijklmnopqrstuvwxzyabcdefg"); render_text->SetCursorPosition(0); int width = render_text->GetStringSize().width(); ASSERT_GT(width, 10); @@ -5627,13 +5623,13 @@ TEST_F(RenderTextTest, SelectionKeepsLigatures) { TEST_F(RenderTextTest, ScriptExtensionsDoNotBreak) { // Apparently ramen restaurants prefer "らーめん" over "らあめん". The "dash" // is the long sound symbol and usually just appears in Katakana writing. - const base::string16 ramen_hiragana = UTF8ToUTF16("らーめん"); - const base::string16 ramen_katakana = UTF8ToUTF16("ラーメン"); - const base::string16 ramen_mixed = UTF8ToUTF16("らあメン"); + const std::u16string ramen_hiragana = u"らーめん"; + const std::u16string ramen_katakana = u"ラーメン"; + const std::u16string ramen_mixed = u"らあメン"; - EXPECT_EQ(std::vector({ramen_hiragana}), + EXPECT_EQ(std::vector({ramen_hiragana}), RunsFor(ramen_hiragana)); - EXPECT_EQ(std::vector({ramen_katakana}), + EXPECT_EQ(std::vector({ramen_katakana}), RunsFor(ramen_katakana)); EXPECT_EQ(ToString16Vec({"らあ", "メン"}), RunsFor(ramen_mixed)); @@ -5646,11 +5642,11 @@ TEST_F(RenderTextTest, WhitespaceDoesBreak) { // Title of the Wikipedia page for "bit". ASCII spaces. In Hebrew and English. // Note that the hyphens that Wikipedia uses are different. English uses // ASCII (U+002D) "hyphen minus", Hebrew uses the U+2013 "EN Dash". - const base::string16 ascii_space_he = UTF8ToUTF16("סיבית – ויקיפדיה"); - const base::string16 ascii_space_en = ASCIIToUTF16("Bit - Wikipedia"); + const std::u16string ascii_space_he = u"סיבית – ויקיפדיה"; + const std::u16string ascii_space_en = u"Bit - Wikipedia"; // This says "thank you very much" with a full-width non-ascii space (U+3000). - const base::string16 full_width_space = UTF8ToUTF16("ども ありがと"); + const std::u16string full_width_space = u"ども ありがと"; EXPECT_EQ(ToString16Vec({"סיבית", " ", "–", " ", "ויקיפדיה"}), RunsFor(ascii_space_he)); @@ -5830,11 +5826,11 @@ TEST_F(RenderTextTest, Multiline_IgnoreElide) { render_text->SetElideBehavior(ELIDE_TAIL); render_text->SetDisplayRect(Rect(20, 1000)); render_text->SetText(base::ASCIIToUTF16(kTestString)); - EXPECT_NE(base::string16::npos, + EXPECT_NE(std::u16string::npos, render_text->GetDisplayText().find(base::UTF8ToUTF16(kEllipsis))); render_text->SetMultiline(true); - EXPECT_EQ(base::string16::npos, + EXPECT_EQ(std::u16string::npos, render_text->GetDisplayText().find(base::UTF8ToUTF16(kEllipsis))); } @@ -5850,7 +5846,7 @@ TEST_F(RenderTextTest, Multiline_NewlineCharacterReplacement) { render_text->SetDisplayRect(Rect(200, 1000)); render_text->SetText(ASCIIToUTF16(kTestStrings[i])); - base::string16 display_text = render_text->GetDisplayText(); + 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()); @@ -5911,8 +5907,8 @@ TEST_F(RenderTextTest, Multiline_HorizontalAlignment) { EXPECT_EQ(0, test_api()->GetAlignmentOffset(0).x()); EXPECT_EQ(0, test_api()->GetAlignmentOffset(1).x()); } else { - std::vector lines = base::SplitString( - base::UTF8ToUTF16(kTestStrings[i].text), base::string16(1, '\n'), + std::vector lines = base::SplitString( + base::UTF8ToUTF16(kTestStrings[i].text), std::u16string(1, '\n'), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); ASSERT_EQ(2u, lines.size()); @@ -5949,7 +5945,7 @@ TEST_F(RenderTextTest, Multiline_WordWrapBehavior) { }; RenderTextHarfBuzz* render_text = GetRenderText(); render_text->SetMultiline(true); - render_text->SetText(ASCIIToUTF16("foo fooooo foo")); + render_text->SetText(u"foo fooooo foo"); SetGlyphWidth(kGlyphSize); render_text->SetDisplayRect(Rect(0, 0, kGlyphSize * 4, 0)); @@ -6049,27 +6045,27 @@ TEST_F(RenderTextTest, Multiline_SurrogatePairsOrCombiningChars) { // 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 base::char16 kSurrogate[] = {0xD834, 0xDD1E, 0}; - const base::string16 text_surrogate(kSurrogate); + const char16_t kSurrogate[] = {0xD834, 0xDD1E, 0}; + const std::u16string text_surrogate(kSurrogate); const int kSurrogateWidth = GetStringWidth(kSurrogate, render_text->font_list()); // 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 base::char16 kCombiningChars[] = {0x921, 0x93F, 0}; - const base::string16 text_combining(kCombiningChars); + const char16_t kCombiningChars[] = {0x921, 0x93F, 0}; + const std::u16string text_combining(kCombiningChars); const int kCombiningCharsWidth = GetStringWidth(kCombiningChars, render_text->font_list()); const struct { - const base::string16 text; + const std::u16string text; const int display_width; const Range char_ranges[3]; } kTestScenarios[] = { {text_surrogate + text_surrogate + text_surrogate, kSurrogateWidth / 2 * 3, {Range(0, 2), Range(2, 4), Range(4, 6)}}, - {text_surrogate + ASCIIToUTF16(" ") + kCombiningChars, + {text_surrogate + u" " + kCombiningChars, std::min(kSurrogateWidth, kCombiningCharsWidth) / 2, {Range(0, 2), Range(2, 3), Range(3, 5)}}, }; @@ -6097,12 +6093,11 @@ TEST_F(RenderTextTest, Multiline_ZeroWidthChars) { render_text->SetMultiline(true); render_text->SetWordWrapBehavior(WRAP_LONG_WORDS); - const base::char16 kZeroWidthSpace = {0x200B}; - const base::string16 text(ASCIIToUTF16("test") + kZeroWidthSpace + + const char16_t kZeroWidthSpace = {0x200B}; + const std::u16string text(ASCIIToUTF16("test") + kZeroWidthSpace + ASCIIToUTF16("\n") + kZeroWidthSpace + ASCIIToUTF16("test.")); - const int kTestWidth = - GetStringWidth(ASCIIToUTF16("test"), render_text->font_list()); + const int kTestWidth = GetStringWidth(u"test", render_text->font_list()); const Range char_ranges[3] = {Range(0, 6), Range(6, 11), Range(11, 12)}; render_text->SetText(text); @@ -6126,7 +6121,7 @@ TEST_F(RenderTextTest, Multiline_ZeroWidthNewline) { RenderTextHarfBuzz* render_text = GetRenderText(); render_text->SetMultiline(true); - const base::string16 text(ASCIIToUTF16("\n\n")); + const std::u16string text(u"\n\n"); render_text->SetText(text); EXPECT_EQ(3u, render_text->GetNumLines()); for (const auto& line : test_api()->lines()) { @@ -6209,11 +6204,11 @@ TEST_F(RenderTextTest, ControlCharacterReplacement) { render_text->SetText(ASCIIToUTF16(kTextWithControlCharacters)); // The control characters should have been replaced by their symbols. - EXPECT_EQ(WideToUTF16(L"␈␍␇␉␊␋␌"), render_text->GetDisplayText()); + EXPECT_EQ(u"␈␍␇␉␊␋␌", render_text->GetDisplayText()); // Setting multiline, the newline character will be back to the original text. render_text->SetMultiline(true); - EXPECT_EQ(WideToUTF16(L"␈\r␇␉\n␋␌"), render_text->GetDisplayText()); + EXPECT_EQ(u"␈\r␇␉\n␋␌", render_text->GetDisplayText()); // The generic control characters should have been replaced by the replacement // codepoints. @@ -6223,7 +6218,7 @@ TEST_F(RenderTextTest, ControlCharacterReplacement) { TEST_F(RenderTextTest, PrivateUseCharacterReplacement) { RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(L"xx\ue78d\ue78fa\U00100042z")); + render_text->SetText(u"xx\ue78d\ue78fa\U00100042z"); // The private use characters should have been replaced. If the code point is // a surrogate pair, it needs to be replaced by two characters. @@ -6232,14 +6227,25 @@ TEST_F(RenderTextTest, PrivateUseCharacterReplacement) { // The private use characters from Area-B must be replaced. The rewrite step // replaced 2 characters by 1 character. - render_text->SetText(WideToUTF16(L"x\U00100000\U00100001\U00100002")); + render_text->SetText(u"x\U00100000\U00100001\U00100002"); EXPECT_EQ(UTF8ToUTF16("x\ufffd\ufffd\ufffd"), render_text->GetDisplayText()); } +TEST_F(RenderTextTest, AppleSpecificPrivateUseCharacterReplacement) { + // see: http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT + RenderText* render_text = GetRenderText(); + render_text->SetText(u"\uf8ff"); +#if defined(OS_APPLE) + EXPECT_EQ(UTF8ToUTF16("\uf8ff"), render_text->GetDisplayText()); +#else + EXPECT_EQ(UTF8ToUTF16("\ufffd"), render_text->GetDisplayText()); +#endif +} + TEST_F(RenderTextTest, InvalidSurrogateCharacterReplacement) { // Text with invalid surrogates (surrogates low 0xDC00 and high 0xD800). RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(L"\xDC00\xD800")); + render_text->SetText(u"\xDC00\xD800"); EXPECT_EQ(UTF8ToUTF16("\ufffd\ufffd"), render_text->GetDisplayText()); } @@ -6365,7 +6371,7 @@ TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemeCases) { for (size_t i = 0; i < base::size(cases); ++i) { SCOPED_TRACE(base::StringPrintf("Case %" PRIuS, i)); - base::string16 text = UTF8ToUTF16(cases[i]); + std::u16string text = UTF8ToUTF16(cases[i]); render_text->SetText(text); const internal::TextRunList* run_list = GetHarfBuzzRunList(); ASSERT_EQ(1U, run_list->size()); @@ -6415,7 +6421,7 @@ TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemePartition) { run.shape.width = 20; RenderTextHarfBuzz* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcd")); + render_text->SetText(u"abcd"); for (size_t i = 0; i < base::size(cases); ++i) { std::copy(cases[i].glyph_to_char, cases[i].glyph_to_char + 2, @@ -6435,7 +6441,7 @@ TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemePartition) { TEST_F(RenderTextTest, HarfBuzz_RunDirection) { RenderTextHarfBuzz* render_text = GetRenderText(); - const base::string16 mixed = UTF8ToUTF16("\u05D0\u05D11234\u05D2\u05D3abc"); + const std::u16string mixed = UTF8ToUTF16("\u05D0\u05D11234\u05D2\u05D3abc"); render_text->SetText(mixed); // Get the run list for both display directions. @@ -6450,7 +6456,7 @@ TEST_F(RenderTextTest, HarfBuzz_RunDirection_URLs) { RenderTextHarfBuzz* render_text = GetRenderText(); // This string, unescaped (logical order): // ‭www.אב.גד/הוabc/def?זח=טי‬ - const base::string16 mixed = UTF8ToUTF16( + const std::u16string mixed = UTF8ToUTF16( "www.\u05D0\u05D1.\u05D2\u05D3/\u05D4\u05D5" "abc/def?\u05D6\u05D7=\u05D8\u05D9"); render_text->SetText(mixed); @@ -6492,13 +6498,13 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { // 😁 (U+1F601, a smile emoji) and ✨ (U+2728, a sparkle icon) can both be // 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(WideToUTF16(L"x\U0001F601y\u2728")); + render_text->SetText(u"x\U0001F601y\u2728"); EXPECT_EQ(ToString16Vec({"x", "😁", "y", "✨"}), 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(UTF8ToUTF16("「🦋」「")); + render_text->SetText(u"「🦋」「"); EXPECT_EQ(ToString16Vec({"「", "🦋", "」「"}), GetRunListStrings()); // Note 🦋 is a surrogate pair [1->2]. EXPECT_EQ("[0][1->2][3->4]", GetRunListStructureString()); @@ -6507,7 +6513,7 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { TEST_F(RenderTextTest, HarfBuzz_BreakRunsByNewline) { RenderText* render_text = GetRenderText(); render_text->SetMultiline(true); - render_text->SetText(ASCIIToUTF16("x\ny")); + render_text->SetText(u"x\ny"); EXPECT_EQ(ToString16Vec({"x", "\n", "y"}), GetRunListStrings()); EXPECT_EQ("[0][1][2]", GetRunListStructureString()); @@ -6645,26 +6651,26 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByAscii) { // ▶ (U+25B6, Geometric Shapes) and an ascii character should have // different runs. - render_text->SetText(WideToUTF16(L"▶z")); + render_text->SetText(u"▶z"); EXPECT_EQ(ToString16Vec({"▶", "z"}), GetRunListStrings()); EXPECT_EQ("[0][1]", GetRunListStructureString()); // ★ (U+2605, Miscellaneous Symbols) and an ascii character should have // different runs. - render_text->SetText(WideToUTF16(L"★1")); + render_text->SetText(u"★1"); EXPECT_EQ(ToString16Vec({"★", "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(WideToUTF16(L"🐱.")); + render_text->SetText(u"🐱."); EXPECT_EQ(ToString16Vec({"🐱", "."}), 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(WideToUTF16(L"🥴$")); + render_text->SetText(u"🥴$"); EXPECT_EQ(ToString16Vec({"🥴", "$"}), GetRunListStrings()); EXPECT_EQ("[0->1][2]", GetRunListStructureString()); } @@ -6675,7 +6681,7 @@ TEST_F(RenderTextTest, EmojiFlagGlyphCount) { RenderText* render_text = GetRenderText(); render_text->SetDisplayRect(Rect(1000, 1000)); // Two flags: UK and Japan. Note macOS 10.9 only has flags for 10 countries. - base::string16 text(UTF8ToUTF16("🇬🇧🇯🇵")); + std::u16string text(u"🇬🇧🇯🇵"); // Each flag is 4 UTF16 characters (2 surrogate pair code points). EXPECT_EQ(8u, text.length()); render_text->SetText(text); @@ -6708,10 +6714,10 @@ TEST_F(RenderTextTest, HarfBuzz_ShapeRunsWithMultipleFonts) { // different fonts. render_text->SetText( UTF8ToUTF16(u8"\U0001F3F3\U0000FE0F\U00000020\U0001F308\U000020E0")); - std::vector expected; - expected.push_back(WideToUTF16(L"\U0001F3F3\U0000FE0F")); - expected.push_back(WideToUTF16(L" ")); - expected.push_back(WideToUTF16(L"\U0001F308\U000020E0")); + std::vector expected; + expected.push_back(u"\U0001F3F3\U0000FE0F"); + expected.push_back(u" "); + expected.push_back(u"\U0001F308\U000020E0"); EXPECT_EQ(expected, GetRunListStrings()); EXPECT_EQ("[0->2][3][4->6]", GetRunListStructureString()); @@ -6745,7 +6751,7 @@ TEST_F(RenderTextTest, GlyphBounds) { // Ensure that shaping with a non-existent font does not cause a crash. TEST_F(RenderTextTest, HarfBuzz_NonExistentFont) { RenderTextHarfBuzz* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("test")); + render_text->SetText(u"test"); const internal::TextRunList* run_list = GetHarfBuzzRunList(); ASSERT_EQ(1U, run_list->size()); internal::TextRunHarfBuzz* run = run_list->runs()[0].get(); @@ -6757,7 +6763,7 @@ TEST_F(RenderTextTest, HarfBuzz_NonExistentFont) { TEST_F(RenderTextTest, HarfBuzz_EmptyRun) { internal::TextRunHarfBuzz run((Font())); RenderTextHarfBuzz* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("abcdefgh")); + render_text->SetText(u"abcdefgh"); run.range = Range(3, 8); run.shape.glyph_count = 0; @@ -6774,7 +6780,7 @@ TEST_F(RenderTextTest, HarfBuzz_EmptyRun) { // actual size. See http://crbug.com/470073 TEST_F(RenderTextTest, HarfBuzz_WordWidthWithDiacritics) { RenderTextHarfBuzz* render_text = GetRenderText(); - const base::string16 kWord = UTF8ToUTF16("\u0906\u092A\u0915\u0947 "); + const std::u16string kWord = UTF8ToUTF16("\u0906\u092A\u0915\u0947 "); render_text->SetText(kWord); const SizeF text_size = render_text->GetStringSizeF(); @@ -6790,7 +6796,7 @@ TEST_F(RenderTextTest, HarfBuzz_WordWidthWithDiacritics) { // Ensure a string fits in a display rect with a width equal to the string's. TEST_F(RenderTextTest, StringFitsOwnWidth) { RenderText* render_text = GetRenderText(); - const base::string16 kString = ASCIIToUTF16("www.example.com"); + const std::u16string kString = u"www.example.com"; render_text->SetText(kString); render_text->ApplyWeight(Font::Weight::BOLD, Range(0, 3)); @@ -7131,7 +7137,7 @@ INSTANTIATE_TEST_SUITE_P(FallbackFontCommonScript, #if defined(OS_WIN) // Ensures that locale is used for fonts selection. TEST_F(RenderTextTest, CJKFontWithLocale) { - const wchar_t kCJKTest[] = L"\u8AA4\u904E\u9AA8"; + const char16_t kCJKTest[] = u"\u8AA4\u904E\u9AA8"; static const char* kLocaleTests[] = {"zh-CN", "ja-JP", "ko-KR"}; std::set tested_font_names; @@ -7140,7 +7146,7 @@ TEST_F(RenderTextTest, CJKFontWithLocale) { ResetRenderTextInstance(); RenderTextHarfBuzz* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(kCJKTest)); + render_text->SetText(kCJKTest); const std::vector font_spans = GetFontSpans(); ASSERT_EQ(font_spans.size(), 1U); @@ -7328,7 +7334,7 @@ TEST_F(RenderTextTest, DISABLED_TextDoesClip) { // Ensure color changes are picked up by the RenderText implementation. TEST_F(RenderTextTest, ColorChange) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("x")); + render_text->SetText(u"x"); Draw(); ExpectTextLog({{1, SK_ColorBLACK}}); @@ -7346,7 +7352,7 @@ TEST_F(RenderTextTest, StylePropagated) { // needed). They also vary depending on the OS version, so set a known font. FontList font_list(Font("Arial", 10)); - render_text->SetText(ASCIIToUTF16("x")); + render_text->SetText(u"x"); render_text->SetFontList(font_list); DrawVisualText(); @@ -7376,7 +7382,7 @@ TEST_F(RenderTextTest, SubpixelRenderingSuppressed) { "your system fonts settings."; RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("x")); + render_text->SetText(u"x"); DrawVisualText(); #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \ @@ -7457,7 +7463,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_LTR) { // TODO(crbug.com/1111044): this shouldn't be necessary once RenderText keeps // float precision through GetCursorBounds(). SetGlyphWidth(5); - const base::string16 ltr = ASCIIToUTF16(" ab c "); + const std::u16string ltr = u" ab c "; const int kWordOneStartIndex = 2; const int kWordTwoStartIndex = 6; @@ -7474,7 +7480,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_LTR) { // Create expected decorated text instances. DecoratedText expected_word_1; - expected_word_1.text = ASCIIToUTF16("ab"); + expected_word_1.text = u"ab"; // Attributes for the characters 'a' and 'b' at logical indices 2 and 3 // respectively. expected_word_1.attributes.push_back(CreateRangedAttribute( @@ -7487,7 +7493,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_LTR) { SelectionModel(kWordOneStartIndex, CURSOR_FORWARD), false); DecoratedText expected_word_2; - expected_word_2.text = ASCIIToUTF16("c"); + expected_word_2.text = u"c"; // Attributes for character 'c' at logical index |kWordTwoStartIndex|. expected_word_2.attributes.push_back( CreateRangedAttribute(font_spans, 0, kWordTwoStartIndex, @@ -7542,7 +7548,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 base::string16 rtl = UTF8ToUTF16(" \u0634\u0632 \u0634"); + const std::u16string rtl = UTF8ToUTF16(" \u0634\u0632 \u0634"); const int kWordOneStartIndex = 1; const int kWordTwoStartIndex = 5; @@ -7619,7 +7625,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_RTL) { // Test that GetWordLookupDataAtPoint behaves correctly for multiline text. TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Multiline) { - const base::string16 text = ASCIIToUTF16("a b\n..\ncd."); + const std::u16string text = u"a b\n..\ncd."; const size_t kWordOneIndex = 0; // Index of character 'a'. const size_t kWordTwoIndex = 2; // Index of character 'b'. const size_t kWordThreeIndex = 7; // Index of character 'c'. @@ -7638,14 +7644,14 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Multiline) { const std::vector font_spans = GetFontSpans(); DecoratedText expected_word_1; - expected_word_1.text = ASCIIToUTF16("a"); + expected_word_1.text = u"a"; expected_word_1.attributes.push_back(CreateRangedAttribute( font_spans, 0, kWordOneIndex, Font::Weight::SEMIBOLD, 0)); const Rect left_glyph_word_1 = GetSubstringBoundsUnion(Range(kWordOneIndex, kWordOneIndex + 1)); DecoratedText expected_word_2; - expected_word_2.text = ASCIIToUTF16("b"); + expected_word_2.text = u"b"; expected_word_2.attributes.push_back(CreateRangedAttribute( font_spans, 0, kWordTwoIndex, Font::Weight::SEMIBOLD, UNDERLINE_MASK | STRIKE_MASK)); @@ -7653,7 +7659,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Multiline) { GetSubstringBoundsUnion(Range(kWordTwoIndex, kWordTwoIndex + 1)); DecoratedText expected_word_3; - expected_word_3.text = ASCIIToUTF16("cd"); + expected_word_3.text = u"cd"; expected_word_3.attributes.push_back( CreateRangedAttribute(font_spans, 0, kWordThreeIndex, Font::Weight::NORMAL, STRIKE_MASK | ITALIC_MASK)); @@ -7698,7 +7704,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Multiline) { // Verify the boolean return value of GetWordLookupDataAtPoint. TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Return) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("...")); + render_text->SetText(u"..."); DecoratedText decorated_word; Point baseline_point; @@ -7710,7 +7716,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Return) { EXPECT_FALSE(render_text->GetWordLookupDataAtPoint(query, &decorated_word, &baseline_point)); - render_text->SetText(ASCIIToUTF16("abc")); + render_text->SetText(u"abc"); query = render_text->GetCursorBounds(SelectionModel(0, CURSOR_FORWARD), false) .origin(); EXPECT_TRUE(render_text->GetWordLookupDataAtPoint(query, &decorated_word, @@ -7726,7 +7732,7 @@ TEST_F(RenderTextTest, GetWordLookupDataAtPoint_Return) { // Test that GetLookupDataAtPoint behaves correctly when the range spans lines. TEST_F(RenderTextTest, GetLookupDataAtRange_Multiline) { - const base::string16 text = ASCIIToUTF16("a\nb"); + const std::u16string text = u"a\nb"; constexpr Range kWordOneRange = Range(0, 1); // Range of character 'a'. constexpr Range kWordTwoRange = Range(2, 3); // Range of character 'b'. constexpr Range kTextRange = Range(0, 3); // Range of the entire text. @@ -7744,20 +7750,20 @@ TEST_F(RenderTextTest, GetLookupDataAtRange_Multiline) { const std::vector font_spans = GetFontSpans(); DecoratedText expected_word_1; - expected_word_1.text = ASCIIToUTF16("a"); + expected_word_1.text = u"a"; expected_word_1.attributes.push_back(CreateRangedAttribute( font_spans, 0, kWordOneRange.start(), Font::Weight::SEMIBOLD, 0)); const Rect left_glyph_word_1 = GetSubstringBoundsUnion(kWordOneRange); DecoratedText expected_word_2; - expected_word_2.text = ASCIIToUTF16("b"); + expected_word_2.text = u"b"; expected_word_2.attributes.push_back( CreateRangedAttribute(font_spans, 0, kWordTwoRange.start(), Font::Weight::NORMAL, UNDERLINE_MASK)); const Rect left_glyph_word_2 = GetSubstringBoundsUnion(kWordTwoRange); DecoratedText expected_entire_text; - expected_entire_text.text = ASCIIToUTF16("a\nb"); + expected_entire_text.text = u"a\nb"; expected_entire_text.attributes.push_back( CreateRangedAttribute(font_spans, kWordOneRange.start(), kWordOneRange.start(), Font::Weight::SEMIBOLD, 0)); @@ -7852,7 +7858,7 @@ TEST_F(RenderTextTest, GetSubstringBounds) { const float kGlyphWidth = 5; SetGlyphWidth(kGlyphWidth); RenderText* render_text = GetRenderText(); - render_text->SetText(UTF8ToUTF16("abc")); + render_text->SetText(u"abc"); render_text->SetCursorEnabled(false); render_text->SetElideBehavior(NO_ELIDE); @@ -7885,7 +7891,7 @@ TEST_F(RenderTextTest, GetSubstringBoundsFloatingPoint) { SetGlyphWidth(kGlyphWidth); RenderText* render_text = GetRenderText(); render_text->SetDisplayRect(Rect(200, 1000)); - render_text->SetText(UTF8ToUTF16("abcdef")); + render_text->SetText(u"abcdef"); gfx::Rect bounds = GetSubstringBoundsUnion(Range(1, 2)); // The bounds should be rounded outwards so that the full substring is always // contained in them. @@ -7899,7 +7905,7 @@ TEST_F(RenderTextTest, GetSubstringBoundsInt) { SetGlyphWidth(kGlyphWidth); RenderText* render_text = GetRenderText(); render_text->SetDisplayRect(Rect(200, 1000)); - render_text->SetText(UTF8ToUTF16("abcdef")); + render_text->SetText(u"abcdef"); gfx::Rect bounds = GetSubstringBoundsUnion(Range(1, 2)); EXPECT_EQ(kGlyphWidth, bounds.x()); EXPECT_EQ(2 * kGlyphWidth, bounds.right()); @@ -7910,7 +7916,7 @@ TEST_F(RenderTextTest, GetSubstringBoundsMultiline) { RenderText* render_text = GetRenderText(); render_text->SetMultiline(true); render_text->SetDisplayRect(Rect(200, 1000)); - render_text->SetText(ASCIIToUTF16("abc\n\ndef")); + render_text->SetText(u"abc\n\ndef"); const std::vector line_char_range = {Range(0, 4), Range(4, 5), Range(5, 8)}; @@ -7943,7 +7949,7 @@ TEST_F(RenderTextTest, InvalidFont) { const int kFontSize = 13; RenderText* render_text = GetRenderText(); render_text->SetFontList(FontList(Font(font_name, kFontSize))); - render_text->SetText(ASCIIToUTF16("abc")); + render_text->SetText(u"abc"); DrawVisualText(); } @@ -8033,7 +8039,7 @@ TEST_F(RenderTextTest, BaselineWithLineHeight) { RenderText* render_text = GetRenderText(); const int font_height = render_text->font_list().GetHeight(); render_text->SetDisplayRect(Rect(500, font_height)); - render_text->SetText(ASCIIToUTF16("abc")); + render_text->SetText(u"abc"); // Select everything so the test can use GetSelectionBoundsUnion(). render_text->SelectAll(false); @@ -8129,7 +8135,7 @@ TEST_F(RenderTextTest, TeluguGraphemeBoundaries) { // combine into a ligature "cluster". But, unlike ligatures in English (e.g. // the "ffl" in "waffle"), this Telugu ligature is laid out vertically, with // both graphemes occupying the same horizontal space. - render_text->SetText(UTF8ToUTF16("క్రొ")); + render_text->SetText(u"క్రొ"); const int whole_width = render_text->GetStringSize().width(); // Sanity check. A typical width is 8 pixels. Anything less than 6 could screw @@ -8165,7 +8171,7 @@ TEST_F(RenderTextTest, MissingFlagEmoji) { // but cursor navigation should still behave as though they are joined. To get // placeholder glyphs, make up a non-existent country. The codes used are // based on ISO 3166-1 alpha-2. Codes starting with X are user-assigned. - base::string16 text(WideToUTF16(L"🇽🇽🇽🇽")); + std::u16string text(u"🇽🇽🇽🇽"); // Each flag is 4 UTF16 characters (2 surrogate pair code points). EXPECT_EQ(8u, text.length()); @@ -8220,7 +8226,7 @@ TEST_F(RenderTextTest, MissingFlagEmoji) { // Ensures that glyph spacing is correctly applied to obscured text. TEST_F(RenderTextTest, ObscuredGlyphSpacing) { - const base::string16 seuss = ASCIIToUTF16("hop on pop"); + const std::u16string seuss = u"hop on pop"; RenderTextHarfBuzz* render_text = GetRenderText(); render_text->SetText(seuss); render_text->SetObscured(true); @@ -8241,7 +8247,7 @@ TEST_F(RenderTextTest, ObscuredGlyphSpacing) { // Ensures that glyph spacing is ignored for non-obscured text. TEST_F(RenderTextTest, ObscuredGlyphSpacingOnNonObscuredText) { - const base::string16 seuss = ASCIIToUTF16("hop on pop"); + const std::u16string seuss = u"hop on pop"; RenderTextHarfBuzz* render_text = GetRenderText(); render_text->SetText(seuss); render_text->SetObscured(false); @@ -8258,7 +8264,7 @@ TEST_F(RenderTextTest, FontSizeOverride) { RenderTextHarfBuzz* render_text = GetRenderText(); const int default_font_size = render_text->font_list().GetFontSize(); const int test_font_size_override = default_font_size + 5; - render_text->SetText(ASCIIToUTF16("0123456789")); + render_text->SetText(u"0123456789"); render_text->ApplyFontSizeOverride(test_font_size_override, gfx::Range(3, 7)); EXPECT_EQ(ToString16Vec({"012", "3456", "789"}), GetRunListStrings()); @@ -8275,7 +8281,7 @@ TEST_F(RenderTextTest, FontSizeOverride) { TEST_F(RenderTextTest, DrawVisualText_WithSelection) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("TheRedElephantIsEatingMyPumpkin")); + render_text->SetText(u"TheRedElephantIsEatingMyPumpkin"); // Ensure selected text is drawn differently than unselected text. render_text->set_selection_color(SK_ColorRED); DrawVisualText({{3, 14}}); @@ -8284,7 +8290,7 @@ TEST_F(RenderTextTest, DrawVisualText_WithSelection) { TEST_F(RenderTextTest, DrawVisualText_WithSelectionOnObcuredEmoji) { RenderText* render_text = GetRenderText(); - render_text->SetText(WideToUTF16(L"\U0001F628\U0001F628\U0001F628")); + render_text->SetText(u"\U0001F628\U0001F628\U0001F628"); render_text->SetObscured(true); render_text->set_selection_color(SK_ColorRED); DrawVisualText({{4, 6}}); @@ -8300,7 +8306,7 @@ TEST_F(RenderTextTest, DrawSelectAll) { {1, SK_ColorBLACK}, {2, SK_ColorRED}, {1, SK_ColorBLACK}}; RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("Test")); + render_text->SetText(u"Test"); render_text->set_selection_color(SK_ColorRED); render_text->SelectRange(Range(1, 3)); @@ -8327,7 +8333,7 @@ TEST_F(RenderTextTest, DrawSelectAll) { #if defined(OS_LINUX) || defined(OS_CHROMEOS) TEST_F(RenderTextTest, StringSizeUpdatedWhenDeviceScaleFactorChanges) { RenderText* render_text = GetRenderText(); - render_text->SetText(ASCIIToUTF16("Test - 1")); + render_text->SetText(u"Test - 1"); const gfx::SizeF initial_size = render_text->GetStringSizeF(); // Non-integer device scale factor enables subpixel positioning on Linux and @@ -8340,7 +8346,7 @@ TEST_F(RenderTextTest, StringSizeUpdatedWhenDeviceScaleFactorChanges) { // a baseline to which compare the original render text string size. ResetRenderTextInstance(); RenderText* scaled_render_text = GetRenderText(); - scaled_render_text->SetText(ASCIIToUTF16("Test - 1")); + scaled_render_text->SetText(u"Test - 1"); // Verify that original render text string size got updated after device scale // factor changed. diff --git a/chromium/ui/gfx/rendering_pipeline.cc b/chromium/ui/gfx/rendering_pipeline.cc index 6790edbf233..a0842f94faa 100644 --- a/chromium/ui/gfx/rendering_pipeline.cc +++ b/chromium/ui/gfx/rendering_pipeline.cc @@ -129,7 +129,6 @@ class RenderingPipelineImpl final : public RenderingPipeline { public: explicit RenderingPipelineImpl(const char* pipeline_type) : pipeline_type_(pipeline_type) { - RenderingStageScheduler::EnsureInitialized(); DETACH_FROM_THREAD(bound_thread_); } ~RenderingPipelineImpl() override { TearDown(); } diff --git a/chromium/ui/gfx/rendering_stage_scheduler.cc b/chromium/ui/gfx/rendering_stage_scheduler.cc index 58c365c9f30..b13643c957a 100644 --- a/chromium/ui/gfx/rendering_stage_scheduler.cc +++ b/chromium/ui/gfx/rendering_stage_scheduler.cc @@ -5,118 +5,39 @@ #include "ui/gfx/rendering_stage_scheduler.h" #include "base/logging.h" -#include "base/native_library.h" #include "base/no_destructor.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #if defined(OS_ANDROID) - -#include -#include - -extern "C" { - -typedef struct APowerManager APowerManager; - -using pAPower_acquireManager = APowerManager* (*)(); -using pAPower_createThreadGroup = int64_t (*)(APowerManager* manager, - pid_t* threadIds, - size_t numThreadIds, - uint64_t desiredDurationMicros); -using pAPower_destroyThreadGroup = - void (*)(APowerManager* manager, int64_t /* ThreadGroupId */ threadGroup); -using pAPower_updateThreadGroupDesiredDuration = - void (*)(APowerManager* manager, - int64_t /* ThreadGroupId */ threadGroup, - uint64_t desiredDurationMicros); -using pAPower_reportThreadGroupDuration = - void (*)(APowerManager* manager, - int64_t /* ThreadGroupId */ threadGroup, - uint64_t actualDurationMicros); -} - +#include "base/android/jni_array.h" +#include "base/android/scoped_java_ref.h" +#include "ui/gfx/gfx_jni_headers/AdpfRenderingStageScheduler_jni.h" #endif // OS_ANDROID namespace gfx { namespace { - #if defined(OS_ANDROID) -#define LOAD_FUNCTION(lib, func) \ - do { \ - func##Fn = reinterpret_cast( \ - base::GetFunctionPointerFromNativeLibrary(lib, #func)); \ - if (!func##Fn) { \ - supported = false; \ - LOG(ERROR) << "Unable to load function " << #func; \ - } \ - } while (0) - -struct AdpfMethods { - static const AdpfMethods& Get() { - static const base::NoDestructor instance; - return *instance; - } - - AdpfMethods() { - base::NativeLibraryLoadError error; - base::NativeLibrary main_dl_handle = - base::LoadNativeLibrary(base::FilePath("libandroid.so"), &error); - if (!main_dl_handle) { - LOG(ERROR) << "Couldnt load libandroid.so: " << error.ToString(); - supported = false; - return; - } - - LOAD_FUNCTION(main_dl_handle, APower_acquireManager); - LOAD_FUNCTION(main_dl_handle, APower_createThreadGroup); - LOAD_FUNCTION(main_dl_handle, APower_destroyThreadGroup); - LOAD_FUNCTION(main_dl_handle, APower_updateThreadGroupDesiredDuration); - LOAD_FUNCTION(main_dl_handle, APower_reportThreadGroupDuration); - } - - ~AdpfMethods() = default; - - bool supported = true; - pAPower_acquireManager APower_acquireManagerFn; - pAPower_createThreadGroup APower_createThreadGroupFn; - pAPower_destroyThreadGroup APower_destroyThreadGroupFn; - pAPower_updateThreadGroupDesiredDuration - APower_updateThreadGroupDesiredDurationFn; - pAPower_reportThreadGroupDuration APower_reportThreadGroupDurationFn; -}; - -APowerManager* GetPowerManager() { - static APowerManager* power_manager = - AdpfMethods::Get().supported - ? AdpfMethods::Get().APower_acquireManagerFn() - : nullptr; - return power_manager; -} - class RenderingStageSchedulerAdpf : public RenderingStageScheduler { public: RenderingStageSchedulerAdpf(const char* pipeline_type, std::vector threads, base::TimeDelta desired_duration) : pipeline_type_(pipeline_type), desired_duration_(desired_duration) { - static_assert(sizeof(base::PlatformThreadId) == sizeof(pid_t), + static_assert(sizeof(base::PlatformThreadId) == sizeof(jint), "thread id types incompatible"); - - if (!GetPowerManager()) - return; - - id_ = AdpfMethods::Get().APower_createThreadGroupFn( - GetPowerManager(), threads.data(), threads.size(), - desired_duration.InMicroseconds()); + JNIEnv* env = base::android::AttachCurrentThread(); + j_object_ = Java_AdpfRenderingStageScheduler_create( + env, base::android::ToJavaIntArray(env, threads), + desired_duration_.InNanoseconds()); } ~RenderingStageSchedulerAdpf() override { - if (!GetPowerManager()) + if (!j_object_) return; - - AdpfMethods::Get().APower_destroyThreadGroupFn(GetPowerManager(), id_); + JNIEnv* env = base::android::AttachCurrentThread(); + Java_AdpfRenderingStageScheduler_destroy(env, j_object_); } void ReportCpuCompletionTime(base::TimeDelta actual_duration) override { @@ -125,30 +46,23 @@ class RenderingStageSchedulerAdpf : public RenderingStageScheduler { TRACE_EVENT_SCOPE_THREAD, "pipeline_type", pipeline_type_, "utilization_percentage", static_cast(actual_duration * 100 / desired_duration_)); - - if (!GetPowerManager()) + if (!j_object_) return; - - AdpfMethods::Get().APower_reportThreadGroupDurationFn( - GetPowerManager(), id_, actual_duration.InMicroseconds()); + JNIEnv* env = base::android::AttachCurrentThread(); + Java_AdpfRenderingStageScheduler_reportCpuCompletionTime( + env, j_object_, actual_duration.InNanoseconds()); } private: - int64_t id_; const char* pipeline_type_; const base::TimeDelta desired_duration_; + base::android::ScopedJavaGlobalRef j_object_; }; #endif // OS_ANDROID } // namespace -void RenderingStageScheduler::EnsureInitialized() { -#if defined(OS_ANDROID) - AdpfMethods::Get(); -#endif -} - std::unique_ptr RenderingStageScheduler::CreateAdpf( const char* pipeline_type, std::vector threads, diff --git a/chromium/ui/gfx/swap_result.h b/chromium/ui/gfx/swap_result.h index 6f74bf2c949..65e01be8046 100644 --- a/chromium/ui/gfx/swap_result.h +++ b/chromium/ui/gfx/swap_result.h @@ -43,6 +43,9 @@ struct SwapTimings { // it's FinishPaintRenderPass/SwapBuffers. base::TimeTicks gpu_started_draw; + // When GPU scheduler removed the last required dependency. + base::TimeTicks gpu_task_ready; + bool is_null() const { return swap_start.is_null() && swap_end.is_null(); } }; diff --git a/chromium/ui/gfx/switches.cc b/chromium/ui/gfx/switches.cc index 16eeda0d910..0f746ead72a 100644 --- a/chromium/ui/gfx/switches.cc +++ b/chromium/ui/gfx/switches.cc @@ -16,10 +16,6 @@ const char kAnimationDurationScale[] = "animation-duration-scale"; const char kDisableFontSubpixelPositioning[] = "disable-font-subpixel-positioning"; -// Disable a NV12 format buffer allocation with -// gfx::BufferUsage::SCANOUT_CPU_READ_WRITE usage. -const char kDisableYuv420Biplanar[] = "disable-yuv420-biplanar"; - // Enable native CPU-mappable GPU memory buffer support on Linux. const char kEnableNativeGpuMemoryBuffers[] = "enable-native-gpu-memory-buffers"; diff --git a/chromium/ui/gfx/switches.h b/chromium/ui/gfx/switches.h index fa86fc52621..f8fc7fe6a54 100644 --- a/chromium/ui/gfx/switches.h +++ b/chromium/ui/gfx/switches.h @@ -12,7 +12,6 @@ namespace switches { GFX_SWITCHES_EXPORT extern const char kAnimationDurationScale[]; GFX_SWITCHES_EXPORT extern const char kDisableFontSubpixelPositioning[]; -GFX_SWITCHES_EXPORT extern const char kDisableYuv420Biplanar[]; GFX_SWITCHES_EXPORT extern const char kEnableNativeGpuMemoryBuffers[]; GFX_SWITCHES_EXPORT extern const char kForcePrefersReducedMotion[]; GFX_SWITCHES_EXPORT extern const char kHeadless[]; diff --git a/chromium/ui/gfx/text_elider.cc b/chromium/ui/gfx/text_elider.cc index 2a80e470579..1ebdfb46b7a 100644 --- a/chromium/ui/gfx/text_elider.cc +++ b/chromium/ui/gfx/text_elider.cc @@ -51,7 +51,7 @@ namespace { // in the middle, splitting available width equally with the elided username. // If the username is short enough that it doesn't need half the available // width, the elided domain will occupy that extra width. -base::string16 ElideEmail(const base::string16& email, +std::u16string ElideEmail(const std::u16string& email, const FontList& font_list, float available_pixel_width) { if (GetStringWidthF(email, font_list) <= available_pixel_width) @@ -61,14 +61,14 @@ base::string16 ElideEmail(const base::string16& email, // spec allows for @ symbols in the username under some special requirements, // but not in the domain part, so splitting at the last @ symbol is safe. const size_t split_index = email.find_last_of('@'); - DCHECK_NE(split_index, base::string16::npos); - base::string16 username = email.substr(0, split_index); - base::string16 domain = email.substr(split_index + 1); + DCHECK_NE(split_index, std::u16string::npos); + std::u16string username = email.substr(0, split_index); + std::u16string domain = email.substr(split_index + 1); DCHECK(!username.empty()); DCHECK(!domain.empty()); // Subtract the @ symbol from the available width as it is mandatory. - const base::string16 kAtSignUTF16 = ASCIIToUTF16("@"); + const std::u16string kAtSignUTF16 = u"@"; available_pixel_width -= GetStringWidthF(kAtSignUTF16, font_list); // Check whether eliding the domain is necessary: if eliding the username @@ -94,7 +94,7 @@ base::string16 ElideEmail(const base::string16& email, // Failing to elide the domain such that at least one character remains // (other than the ellipsis itself) remains: return a single ellipsis. if (domain.length() <= 1U) - return base::string16(kEllipsisUTF16); + return std::u16string(kEllipsisUTF16); } // Fit the username in the remaining width (at this point the elided username @@ -115,11 +115,11 @@ bool GetDefaultWhitespaceElision(bool elide_in_middle, // U+2026 in utf8 const char kEllipsis[] = "\xE2\x80\xA6"; -const base::char16 kEllipsisUTF16[] = { 0x2026, 0 }; -const base::char16 kForwardSlash = '/'; +const char16_t kEllipsisUTF16[] = {0x2026, 0}; +const char16_t kForwardSlash = '/'; -StringSlicer::StringSlicer(const base::string16& text, - const base::string16& ellipsis, +StringSlicer::StringSlicer(const std::u16string& text, + const std::u16string& ellipsis, bool elide_in_middle, bool elide_at_beginning, base::Optional elide_whitespace) @@ -133,10 +133,10 @@ StringSlicer::StringSlicer(const base::string16& text, elide_at_beginning)) { } -base::string16 StringSlicer::CutString(size_t length, +std::u16string StringSlicer::CutString(size_t length, bool insert_ellipsis) const { - const base::string16 ellipsis_text = - insert_ellipsis ? ellipsis_ : base::string16(); + const std::u16string ellipsis_text = + insert_ellipsis ? ellipsis_ : std::u16string(); // For visual consistency, when eliding at either end of the string, excess // space should be trimmed from the text to return "Foo bar..." instead of @@ -169,21 +169,21 @@ base::string16 StringSlicer::CutString(size_t length, text_.substr(suffix_start); } -base::string16 ElideFilename(const base::FilePath& filename, +std::u16string ElideFilename(const base::FilePath& filename, const FontList& font_list, float available_pixel_width) { #if defined(OS_WIN) - base::string16 filename_utf16 = WideToUTF16(filename.value()); - base::string16 extension = WideToUTF16(filename.Extension()); - base::string16 rootname = + std::u16string filename_utf16 = WideToUTF16(filename.value()); + std::u16string extension = WideToUTF16(filename.Extension()); + std::u16string rootname = WideToUTF16(filename.BaseName().RemoveExtension().value()); #elif defined(OS_POSIX) || defined(OS_FUCHSIA) - base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide( - filename.value())); - base::string16 extension = WideToUTF16(base::SysNativeMBToWide( - filename.Extension())); - base::string16 rootname = WideToUTF16(base::SysNativeMBToWide( - filename.BaseName().RemoveExtension().value())); + std::u16string filename_utf16 = + WideToUTF16(base::SysNativeMBToWide(filename.value())); + std::u16string extension = + WideToUTF16(base::SysNativeMBToWide(filename.Extension())); + std::u16string rootname = WideToUTF16( + base::SysNativeMBToWide(filename.BaseName().RemoveExtension().value())); #endif const float full_width = GetStringWidthF(filename_utf16, font_list); @@ -191,7 +191,7 @@ base::string16 ElideFilename(const base::FilePath& filename, return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16); if (rootname.empty() || extension.empty()) { - const base::string16 elided_name = + const std::u16string elided_name = ElideText(filename_utf16, font_list, available_pixel_width, ELIDE_TAIL); return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); } @@ -201,24 +201,24 @@ base::string16 ElideFilename(const base::FilePath& filename, // We may have trimmed the path. if (root_width + ext_width <= available_pixel_width) { - const base::string16 elided_name = rootname + extension; + const std::u16string elided_name = rootname + extension; return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); } if (ext_width >= available_pixel_width) { - const base::string16 elided_name = ElideText( + const std::u16string elided_name = ElideText( rootname + extension, font_list, available_pixel_width, ELIDE_MIDDLE); return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); } float available_root_width = available_pixel_width - ext_width; - base::string16 elided_name = + std::u16string elided_name = ElideText(rootname, font_list, available_root_width, ELIDE_TAIL); elided_name += extension; return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); } -base::string16 ElideText(const base::string16& text, +std::u16string ElideText(const std::u16string& text, const FontList& font_list, float available_pixel_width, ElideBehavior behavior) { @@ -245,18 +245,18 @@ base::string16 ElideText(const base::string16& text, const bool elide_in_middle = (behavior == ELIDE_MIDDLE); const bool elide_at_beginning = (behavior == ELIDE_HEAD); const bool insert_ellipsis = (behavior != TRUNCATE); - const base::string16 ellipsis = base::string16(kEllipsisUTF16); + const std::u16string ellipsis = std::u16string(kEllipsisUTF16); StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); if (insert_ellipsis && GetStringWidthF(ellipsis, font_list) > available_pixel_width) - return base::string16(); + return std::u16string(); // Use binary search to compute the elided text. size_t lo = 0; size_t hi = text.length() - 1; size_t guess; - base::string16 cut; + std::u16string cut; for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { // We check the width of the whole desired string at once to ensure we // handle kerning/ligatures/etc. correctly. @@ -280,9 +280,9 @@ base::string16 ElideText(const base::string16& text, #endif } -bool ElideString(const base::string16& input, +bool ElideString(const std::u16string& input, size_t max_len, - base::string16* output) { + std::u16string* output) { if (input.length() <= max_len) { output->assign(input); return false; @@ -299,17 +299,17 @@ bool ElideString(const base::string16& input, output->assign(input.substr(0, 2)); break; case 3: - output->assign(input.substr(0, 1) + ASCIIToUTF16(".") + + output->assign(input.substr(0, 1) + u"." + input.substr(input.length() - 1)); break; case 4: - output->assign(input.substr(0, 1) + ASCIIToUTF16("..") + + output->assign(input.substr(0, 1) + u".." + input.substr(input.length() - 1)); break; default: { size_t rstr_len = (max_len - 3) / 2; size_t lstr_len = rstr_len + ((max_len - 3) % 2); - output->assign(input.substr(0, lstr_len) + ASCIIToUTF16("...") + + output->assign(input.substr(0, lstr_len) + u"..." + input.substr(input.length() - rstr_len)); break; } @@ -325,8 +325,10 @@ namespace { // can be broken into smaller methods sharing this state. class RectangleString { public: - RectangleString(size_t max_rows, size_t max_cols, - bool strict, base::string16 *output) + RectangleString(size_t max_rows, + size_t max_cols, + bool strict, + std::u16string* output) : max_rows_(max_rows), max_cols_(max_cols), current_row_(0), @@ -343,7 +345,7 @@ class RectangleString { // AddString() may be called multiple times to concatenate together // multiple strings into the region (the current caller doesn't do // this, however). - void AddString(const base::string16& input); + void AddString(const std::u16string& input); // Perform any deferred output processing. Must be called after the // last AddString() call has occurred. @@ -352,15 +354,15 @@ class RectangleString { private: // Add a line to the rectangular region at the current position, // either by itself or by breaking it into words. - void AddLine(const base::string16& line); + void AddLine(const std::u16string& line); // Add a word to the rectangular region at the current position, // either by itself or by breaking it into characters. - void AddWord(const base::string16& word); + void AddWord(const std::u16string& word); // Add text to the output string if the rectangular boundaries // have not been exceeded, advancing the current position. - void Append(const base::string16& string); + void Append(const std::u16string& string); // Set the current position to the beginning of the next line. If // |output| is true, add a newline to the output string if the rectangular @@ -392,12 +394,12 @@ class RectangleString { bool suppressed_; // String onto which the output is accumulated. - base::string16* output_; + std::u16string* output_; DISALLOW_COPY_AND_ASSIGN(RectangleString); }; -void RectangleString::AddString(const base::string16& input) { +void RectangleString::AddString(const std::u16string& input) { base::i18n::BreakIterator lines(input, base::i18n::BreakIterator::BREAK_NEWLINE); if (lines.Init()) { @@ -410,13 +412,13 @@ void RectangleString::AddString(const base::string16& input) { bool RectangleString::Finalize() { if (suppressed_) { - output_->append(ASCIIToUTF16("...")); + output_->append(u"..."); return true; } return false; } -void RectangleString::AddLine(const base::string16& line) { +void RectangleString::AddLine(const std::u16string& line) { if (line.length() < max_cols_) { Append(line); } else { @@ -434,7 +436,7 @@ void RectangleString::AddLine(const base::string16& line) { current_col_ = 0; } -void RectangleString::AddWord(const base::string16& word) { +void RectangleString::AddWord(const std::u16string& word) { if (word.length() < max_cols_) { // Word can be made to fit, no need to fragment it. if (current_col_ + word.length() >= max_cols_) @@ -460,7 +462,7 @@ void RectangleString::AddWord(const base::string16& word) { } } -void RectangleString::Append(const base::string16& string) { +void RectangleString::Append(const std::u16string& string) { if (current_row_ < max_rows_) output_->append(string); else @@ -471,7 +473,7 @@ void RectangleString::Append(const base::string16& string) { void RectangleString::NewLine(bool output) { if (current_row_ < max_rows_) { if (output) - output_->append(ASCIIToUTF16("\n")); + output_->append(u"\n"); } else { suppressed_ = true; } @@ -488,7 +490,7 @@ class RectangleText { float available_pixel_width, int available_pixel_height, WordWrapBehavior wrap_behavior, - std::vector* lines) + std::vector* lines) : font_list_(font_list), line_height_(font_list.GetHeight()), available_pixel_width_(available_pixel_width), @@ -504,7 +506,7 @@ class RectangleText { // AddString() may be called multiple times to concatenate together // multiple strings into the region (the current caller doesn't do // this, however). - void AddString(const base::string16& input); + void AddString(const std::u16string& input); // Perform any deferred output processing. Must be called after the last // AddString() call has occurred. Returns a combination of @@ -515,24 +517,24 @@ class RectangleText { private: // Add a line to the rectangular region at the current position, // either by itself or by breaking it into words. - void AddLine(const base::string16& line); + void AddLine(const std::u16string& line); // Wrap the specified word across multiple lines. - int WrapWord(const base::string16& word); + int WrapWord(const std::u16string& word); // Add a long word - wrapping, eliding or truncating per the wrap behavior. - int AddWordOverflow(const base::string16& word); + int AddWordOverflow(const std::u16string& word); // Add a word to the rectangular region at the current position. - int AddWord(const base::string16& word); + int AddWord(const std::u16string& word); // Append the specified |text| to the current output line, incrementing the // running width by the specified amount. This is an optimization over // |AddToCurrentLine()| when |text_width| is already known. - void AddToCurrentLineWithWidth(const base::string16& text, float text_width); + void AddToCurrentLineWithWidth(const std::u16string& text, float text_width); // Append the specified |text| to the current output line. - void AddToCurrentLine(const base::string16& text); + void AddToCurrentLine(const std::u16string& text); // Set the current position to the beginning of the next line. bool NewLine(); @@ -559,13 +561,13 @@ class RectangleText { int current_height_ = 0; // The current line of text. - base::string16 current_line_; + std::u16string current_line_; // Indicates whether the last line ended with \n. bool last_line_ended_in_lf_ = false; // The output vector of lines. - std::vector* lines_; + std::vector* lines_; // Indicates whether a word was so long that it had to be truncated or elided // to fit the available width. @@ -580,12 +582,12 @@ class RectangleText { DISALLOW_COPY_AND_ASSIGN(RectangleText); }; -void RectangleText::AddString(const base::string16& input) { +void RectangleText::AddString(const std::u16string& input) { base::i18n::BreakIterator lines(input, base::i18n::BreakIterator::BREAK_NEWLINE); if (lines.Init()) { while (!insufficient_height_ && lines.Advance()) { - base::string16 line = lines.GetString(); + std::u16string line = lines.GetString(); // The BREAK_NEWLINE iterator will keep the trailing newline character, // except in the case of the last line, which may not have one. Remove // the newline character, if it exists. @@ -608,13 +610,13 @@ int RectangleText::Finalize() { lines_->pop_back(); } if (last_line_ended_in_lf_) - lines_->push_back(base::string16()); + lines_->push_back(std::u16string()); return (insufficient_width_ ? INSUFFICIENT_SPACE_HORIZONTAL : 0) | (insufficient_height_ ? INSUFFICIENT_SPACE_VERTICAL : 0) | (first_word_truncated_ ? INSUFFICIENT_SPACE_FOR_FIRST_WORD : 0); } -void RectangleText::AddLine(const base::string16& line) { +void RectangleText::AddLine(const std::u16string& line) { const float line_width = GetStringWidthF(line, font_list_); if (line_width <= available_pixel_width_) { AddToCurrentLineWithWidth(line, line_width); @@ -626,7 +628,7 @@ void RectangleText::AddLine(const base::string16& line) { if (words.Init()) { while (words.Advance()) { const bool truncate = !current_line_.empty(); - const base::string16& word = words.GetString(); + const std::u16string& word = words.GetString(); const int lines_added = AddWord(word); if (lines_added) { if (truncate) { @@ -650,13 +652,13 @@ void RectangleText::AddLine(const base::string16& line) { NewLine(); } -int RectangleText::WrapWord(const base::string16& word) { +int RectangleText::WrapWord(const std::u16string& word) { // Word is so wide that it must be fragmented. - base::string16 text = word; + std::u16string text = word; int lines_added = 0; bool first_fragment = true; while (!insufficient_height_ && !text.empty()) { - base::string16 fragment = + std::u16string fragment = ElideText(text, font_list_, available_pixel_width_, TRUNCATE); // At least one character has to be added at every line, even if the // available space is too small. @@ -671,7 +673,7 @@ int RectangleText::WrapWord(const base::string16& word) { return lines_added; } -int RectangleText::AddWordOverflow(const base::string16& word) { +int RectangleText::AddWordOverflow(const std::u16string& word) { int lines_added = 0; // Unless this is the very first word, put it on a new line. @@ -691,7 +693,7 @@ int RectangleText::AddWordOverflow(const base::string16& word) { } else { const ElideBehavior elide_behavior = (wrap_behavior_ == ELIDE_LONG_WORDS ? ELIDE_TAIL : TRUNCATE); - const base::string16 elided_word = + const std::u16string elided_word = ElideText(word, font_list_, available_pixel_width_, elide_behavior); AddToCurrentLine(elided_word); insufficient_width_ = true; @@ -700,9 +702,9 @@ int RectangleText::AddWordOverflow(const base::string16& word) { return lines_added; } -int RectangleText::AddWord(const base::string16& word) { +int RectangleText::AddWord(const std::u16string& word) { int lines_added = 0; - base::string16 trimmed; + std::u16string trimmed; base::TrimWhitespace(word, base::TRIM_TRAILING, &trimmed); const float trimmed_width = GetStringWidthF(trimmed, font_list_); if (trimmed_width <= available_pixel_width_) { @@ -718,11 +720,11 @@ int RectangleText::AddWord(const base::string16& word) { return lines_added; } -void RectangleText::AddToCurrentLine(const base::string16& text) { +void RectangleText::AddToCurrentLine(const std::u16string& text) { AddToCurrentLineWithWidth(text, GetStringWidthF(text, font_list_)); } -void RectangleText::AddToCurrentLineWithWidth(const base::string16& text, +void RectangleText::AddToCurrentLineWithWidth(const std::u16string& text, float text_width) { if (current_height_ >= available_pixel_height_) { insufficient_height_ = true; @@ -748,21 +750,23 @@ bool RectangleText::NewLine() { } // namespace -bool ElideRectangleString(const base::string16& input, size_t max_rows, - size_t max_cols, bool strict, - base::string16* output) { +bool ElideRectangleString(const std::u16string& input, + size_t max_rows, + size_t max_cols, + bool strict, + std::u16string* output) { RectangleString rect(max_rows, max_cols, strict, output); rect.Init(); rect.AddString(input); return rect.Finalize(); } -int ElideRectangleText(const base::string16& input, +int ElideRectangleText(const std::u16string& input, const FontList& font_list, float available_pixel_width, int available_pixel_height, WordWrapBehavior wrap_behavior, - std::vector* lines) { + std::vector* lines) { RectangleText rect(font_list, available_pixel_width, available_pixel_height, wrap_behavior, lines); rect.Init(); @@ -770,7 +774,7 @@ int ElideRectangleText(const base::string16& input, return rect.Finalize(); } -base::string16 TruncateString(const base::string16& string, +std::u16string TruncateString(const std::u16string& string, size_t length, BreakType break_type) { const bool word_break = break_type == WORD_BREAK; @@ -780,10 +784,10 @@ base::string16 TruncateString(const base::string16& string, return string; // No need to elide. if (length == 0) - return base::string16(); // No room for anything, even an ellipsis. + return std::u16string(); // No room for anything, even an ellipsis. // Added to the end of strings that are too big. - static const base::char16 kElideString[] = { 0x2026, 0 }; + static const char16_t kElideString[] = {0x2026, 0}; if (length == 1) return kElideString; // Only room for an ellipsis. diff --git a/chromium/ui/gfx/text_elider.h b/chromium/ui/gfx/text_elider.h index 8c1b77d2f9c..845666bdc3e 100644 --- a/chromium/ui/gfx/text_elider.h +++ b/chromium/ui/gfx/text_elider.h @@ -14,7 +14,6 @@ #include "base/macros.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "build/build_config.h" #include "ui/gfx/gfx_export.h" #include "ui/gfx/text_constants.h" @@ -27,8 +26,8 @@ namespace gfx { class FontList; GFX_EXPORT extern const char kEllipsis[]; -GFX_EXPORT extern const base::char16 kEllipsisUTF16[]; -GFX_EXPORT extern const base::char16 kForwardSlash; +GFX_EXPORT extern const char16_t kEllipsisUTF16[]; +GFX_EXPORT extern const char16_t kForwardSlash; // Helper class to split + elide text, while respecting UTF-16 surrogate pairs // and combining character sequences. @@ -41,8 +40,8 @@ class GFX_EXPORT StringSlicer { // 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. - StringSlicer(const base::string16& text, - const base::string16& ellipsis, + StringSlicer(const std::u16string& text, + const std::u16string& ellipsis, bool elide_in_middle, bool elide_at_beginning, base::Optional elide_whitespace = base::nullopt); @@ -56,14 +55,14 @@ class GFX_EXPORT StringSlicer { // |length| limit). // Note: Characters may still be omitted even if |length| is the full string // length, if surrogate pairs fall on the split boundary. - base::string16 CutString(size_t length, bool insert_ellipsis) const; + std::u16string CutString(size_t length, bool insert_ellipsis) const; private: // The text to be sliced. - const base::string16& text_; + const std::u16string& text_; // Ellipsis string to use. - const base::string16& ellipsis_; + const std::u16string& ellipsis_; // If true, the middle of the string will be elided. const bool elide_in_middle_; @@ -78,7 +77,7 @@ class GFX_EXPORT StringSlicer { }; // Elides |text| to fit the |available_pixel_width| with the specified behavior. -GFX_EXPORT base::string16 ElideText(const base::string16& text, +GFX_EXPORT std::u16string ElideText(const std::u16string& text, const gfx::FontList& font_list, float available_pixel_width, ElideBehavior elide_behavior); @@ -89,7 +88,7 @@ GFX_EXPORT base::string16 ElideText(const base::string16& text, // filename is forced to have LTR directionality, which means that in RTL UI // the elided filename is wrapped with LRE (Left-To-Right Embedding) mark and // PDF (Pop Directional Formatting) mark. -GFX_EXPORT base::string16 ElideFilename(const base::FilePath& filename, +GFX_EXPORT std::u16string ElideFilename(const base::FilePath& filename, const gfx::FontList& font_list, float available_pixel_width); @@ -100,13 +99,14 @@ GFX_EXPORT base::string16 ElideFilename(const base::FilePath& filename, // If the size of |input| is more than |max_len|, this function returns // true and |input| is shortened into |output| by removing chars in the // middle (they are replaced with up to 3 dots, as size permits). -// Ex: ElideString(ASCIIToUTF16("Hello"), 10, &str) puts Hello in str and -// returns false. ElideString(ASCIIToUTF16("Hello my name is Tom"), 10, &str) +// Ex: ElideString(u"Hello", 10, &str) puts Hello in str and +// returns false. ElideString(u"Hello my name is Tom", 10, &str) // puts "Hell...Tom" in str and returns true. // TODO(tsepez): Doesn't handle UTF-16 surrogate pairs properly. // TODO(tsepez): Doesn't handle bidi properly. -GFX_EXPORT bool ElideString(const base::string16& input, size_t max_len, - base::string16* output); +GFX_EXPORT bool ElideString(const std::u16string& input, + size_t max_len, + std::u16string* output); // Reformat |input| into |output| so that it fits into a |max_rows| by // |max_cols| rectangle of characters. Input newlines are respected, but @@ -117,11 +117,11 @@ GFX_EXPORT bool ElideString(const base::string16& input, size_t max_len, // intra-word (respecting UTF-16 surrogate pairs) as necessary. Truncation // (indicated by an added 3 dots) occurs if the result is still too long. // Returns true if the input had to be truncated (and not just reformatted). -GFX_EXPORT bool ElideRectangleString(const base::string16& input, +GFX_EXPORT bool ElideRectangleString(const std::u16string& input, size_t max_rows, size_t max_cols, bool strict, - base::string16* output); + std::u16string* output); // Indicates whether the |available_pixel_width| by |available_pixel_height| // rectangle passed to |ElideRectangleText()| had insufficient space to @@ -140,19 +140,19 @@ enum ReformattingResultFlags { // param. Returns a combination of |ReformattingResultFlags| that indicate // whether the given rectangle had insufficient space to accommodate |text|, // leading to elision or truncation (and not just reformatting). -GFX_EXPORT int ElideRectangleText(const base::string16& text, +GFX_EXPORT int ElideRectangleText(const std::u16string& text, const gfx::FontList& font_list, float available_pixel_width, int available_pixel_height, WordWrapBehavior wrap_behavior, - std::vector* lines); + std::vector* lines); // Truncates |string| to |length| characters. This breaks the string according // to the specified |break_type|, which must be either WORD_BREAK or // CHARACTER_BREAK, and adds the horizontal ellipsis character (unicode // character 0x2026) to render "...". The supplied string is returned if the // string has |length| characters or less. -GFX_EXPORT base::string16 TruncateString(const base::string16& string, +GFX_EXPORT std::u16string TruncateString(const std::u16string& string, size_t length, BreakType break_type); diff --git a/chromium/ui/gfx/text_elider_unittest.cc b/chromium/ui/gfx/text_elider_unittest.cc index 5839ba76d76..608406246f9 100644 --- a/chromium/ui/gfx/text_elider_unittest.cc +++ b/chromium/ui/gfx/text_elider_unittest.cc @@ -31,7 +31,6 @@ using base::ASCIIToUTF16; using base::UTF16ToUTF8; using base::UTF16ToWide; using base::UTF8ToUTF16; -using base::WideToUTF16; namespace gfx { @@ -51,8 +50,8 @@ struct FileTestcase { }; struct UTF16Testcase { - const base::string16 input; - const base::string16 output; + const std::u16string input; + const std::u16string output; }; struct TestData { @@ -110,7 +109,7 @@ TEST(TextEliderTest, ElideEmail) { const FontList font_list; for (size_t i = 0; i < base::size(testcases); ++i) { - const base::string16 expected_output = UTF8ToUTF16(testcases[i].output); + 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), @@ -133,7 +132,7 @@ TEST(TextEliderTest, ElideEmailMoreSpace) { const FontList font_list; for (const auto* test_email : test_emails) { - const base::string16 test_email16 = UTF8ToUTF16(test_email); + const std::u16string test_email16 = UTF8ToUTF16(test_email); const int mimimum_width = GetStringWidth(test_email16, font_list); for (int extra_space : test_widths_extra_spaces) { // Extra space is available: the email should not be elided. @@ -186,8 +185,8 @@ TEST(TextEliderTest, TestFilenameEliding) { static const FontList font_list; for (size_t i = 0; i < base::size(testcases); ++i) { base::FilePath filepath(testcases[i].input); - base::string16 expected = UTF8ToUTF16(testcases[i].output); - base::string16 using_width_of = UTF8ToUTF16( + 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); expected = base::i18n::GetDisplayStringInLTRDirectionality(expected); @@ -199,7 +198,7 @@ TEST(TextEliderTest, TestFilenameEliding) { TEST(TextEliderTest, ElideTextTruncate) { const FontList font_list; - const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list); + const float kTestWidth = GetStringWidthF(u"Test", font_list); struct TestData { const char* input; float width; @@ -214,7 +213,7 @@ TEST(TextEliderTest, ElideTextTruncate) { }; for (size_t i = 0; i < base::size(cases); ++i) { - base::string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list, + std::u16string result = ElideText(UTF8ToUTF16(cases[i].input), font_list, cases[i].width, TRUNCATE); EXPECT_EQ(cases[i].output, UTF16ToUTF8(result)); } @@ -222,7 +221,7 @@ TEST(TextEliderTest, ElideTextTruncate) { TEST(TextEliderTest, ElideTextEllipsis) { const FontList font_list; - const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list); + const float kTestWidth = GetStringWidthF(u"Test", font_list); const char* kEllipsis = "\xE2\x80\xA6"; const float kEllipsisWidth = GetStringWidthF(UTF8ToUTF16(kEllipsis), font_list); @@ -240,7 +239,7 @@ TEST(TextEliderTest, ElideTextEllipsis) { }; for (size_t i = 0; i < base::size(cases); ++i) { - base::string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list, + std::u16string result = ElideText(UTF8ToUTF16(cases[i].input), font_list, cases[i].width, ELIDE_TAIL); EXPECT_EQ(cases[i].output, UTF16ToUTF8(result)); } @@ -248,7 +247,7 @@ TEST(TextEliderTest, ElideTextEllipsis) { TEST(TextEliderTest, ElideTextEllipsisFront) { const FontList font_list; - const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list); + const float kTestWidth = GetStringWidthF(u"Test", font_list); const std::string kEllipsisStr(kEllipsis); const float kEllipsisWidth = GetStringWidthF(UTF8ToUTF16(kEllipsis), font_list); @@ -257,19 +256,19 @@ TEST(TextEliderTest, ElideTextEllipsisFront) { struct TestData { const char* input; float width; - const base::string16 output; + const std::u16string output; } cases[] = { - { "", 0, base::string16() }, - { "Test", 0, base::string16() }, - { "Test", kEllipsisWidth, UTF8ToUTF16(kEllipsisStr) }, - { "", kTestWidth, base::string16() }, - { "Tes", kTestWidth, ASCIIToUTF16("Tes") }, - { "Test", kTestWidth, ASCIIToUTF16("Test") }, - { "Test123", kEllipsis23Width, UTF8ToUTF16(kEllipsisStr + "23") }, + {"", 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")}, }; for (size_t i = 0; i < base::size(cases); ++i) { - base::string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list, + std::u16string result = ElideText(UTF8ToUTF16(cases[i].input), font_list, cases[i].width, ELIDE_HEAD); EXPECT_EQ(cases[i].output, result); } @@ -278,9 +277,9 @@ TEST(TextEliderTest, ElideTextEllipsisFront) { // Checks that all occurrences of |first_char| are followed by |second_char| and // all occurrences of |second_char| are preceded by |first_char| in |text|. Can // be used to test surrogate pairs or two-character combining sequences. -static void CheckCodeUnitPairs(const base::string16& text, - base::char16 first_char, - base::char16 second_char) { +static void CheckCodeUnitPairs(const std::u16string& text, + char16_t first_char, + char16_t second_char) { for (size_t index = 0; index < text.length(); ++index) { EXPECT_NE(second_char, text[index]); if (text[index] == first_char) { @@ -301,21 +300,21 @@ TEST(TextEliderTest, ElideTextAtomicSequences) { const FontList font_list; // 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 base::char16 kSurrogate[] = {0xD834, 0xDD1E, 0}; + const char16_t kSurrogate[] = {0xD834, 0xDD1E, 0}; // 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 base::char16 kCombiningSequence[] = {0x921, 0x93F, 0}; - std::vector pairs; + const char16_t kCombiningSequence[] = {0x921, 0x93F, 0}; + std::vector pairs; pairs.push_back(kSurrogate); pairs.push_back(kCombiningSequence); - for (const base::string16& pair : pairs) { - base::char16 first_char = pair[0]; - base::char16 second_char = pair[1]; - base::string16 test_string = pair + UTF8ToUTF16("x") + pair; + 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; SCOPED_TRACE(test_string); const float test_string_width = GetStringWidthF(test_string, font_list); - base::string16 result; + std::u16string result; // Elide |text_string| to all possible widths and check that no instance of // |pair| was split in two. @@ -336,23 +335,23 @@ TEST(TextEliderTest, ElideTextAtomicSequences) { } TEST(TextEliderTest, ElideTextLongStrings) { - const base::string16 kEllipsisStr = UTF8ToUTF16(kEllipsis); - base::string16 data_scheme(UTF8ToUTF16("data:text/plain,")); + const std::u16string kEllipsisStr = UTF8ToUTF16(kEllipsis); + std::u16string data_scheme(UTF8ToUTF16("data:text/plain,")); size_t data_scheme_length = data_scheme.length(); - base::string16 ten_a(10, 'a'); - base::string16 hundred_a(100, 'a'); - base::string16 thousand_a(1000, 'a'); - base::string16 ten_thousand_a(10000, 'a'); - base::string16 hundred_thousand_a(100000, 'a'); - base::string16 million_a(1000000, 'a'); + 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'); // 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; - base::string16 long_string_end( - data_scheme + base::string16(number_of_as, 'a') + kEllipsisStr); + 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 }, @@ -377,9 +376,9 @@ TEST(TextEliderTest, ElideTextLongStrings) { } size_t number_of_trailing_as = (data_scheme_length + number_of_as) / 2; - base::string16 long_string_middle( - data_scheme + base::string16(number_of_as - number_of_trailing_as, 'a') + - kEllipsisStr + base::string16(number_of_trailing_as, 'a')); + 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')); #if !defined(OS_IOS) long_string_middle += kEllipsisStr; #endif @@ -405,8 +404,8 @@ TEST(TextEliderTest, ElideTextLongStrings) { ellipsis_width, ELIDE_MIDDLE)); } - base::string16 long_string_beginning( - kEllipsisStr + base::string16(number_of_as, 'a')); + std::u16string long_string_beginning(kEllipsisStr + + std::u16string(number_of_as, 'a')); #if !defined(OS_IOS) long_string_beginning += kEllipsisStr; #endif @@ -435,12 +434,12 @@ TEST(TextEliderTest, ElideTextLongStrings) { TEST(TextEliderTest, StringSlicerBasicTest) { // Must store strings in variables (StringSlicer retains a reference to them). - base::string16 text(UTF8ToUTF16("Hello, world!")); - base::string16 ellipsis(kEllipsisUTF16); + std::u16string text(UTF8ToUTF16("Hello, world!")); + std::u16string ellipsis(kEllipsisUTF16); StringSlicer slicer(text, ellipsis, false, false); EXPECT_EQ(UTF8ToUTF16(""), slicer.CutString(0, false)); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(0, true)); + EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer.CutString(0, true)); EXPECT_EQ(UTF8ToUTF16("Hell"), slicer.CutString(4, false)); EXPECT_EQ(UTF8ToUTF16("Hell") + kEllipsisUTF16, slicer.CutString(4, true)); @@ -461,8 +460,8 @@ TEST(TextEliderTest, StringSlicerBasicTest) { TEST(TextEliderTest, StringSlicerWhitespace_UseDefault) { // Must store strings in variables (StringSlicer retains a reference to them). - base::string16 text(UTF8ToUTF16("Hello, world!")); - base::string16 ellipsis(kEllipsisUTF16); + std::u16string text(UTF8ToUTF16("Hello, world!")); + std::u16string ellipsis(kEllipsisUTF16); // Eliding the end of a string should result in whitespace being removed // before the ellipsis by default. @@ -498,8 +497,8 @@ TEST(TextEliderTest, StringSlicerWhitespace_UseDefault) { TEST(TextEliderTest, StringSlicerWhitespace_NoTrim) { // Must store strings in variables (StringSlicer retains a reference to them). - base::string16 text(UTF8ToUTF16("Hello, world!")); - base::string16 ellipsis(kEllipsisUTF16); + std::u16string text(UTF8ToUTF16("Hello, world!")); + std::u16string ellipsis(kEllipsisUTF16); // Eliding the end of a string should not result in whitespace being removed // before the ellipsis in no-trim mode. @@ -535,8 +534,8 @@ TEST(TextEliderTest, StringSlicerWhitespace_NoTrim) { TEST(TextEliderTest, StringSlicerWhitespace_Trim) { // Must store strings in variables (StringSlicer retains a reference to them). - base::string16 text(UTF8ToUTF16("Hello, world!")); - base::string16 ellipsis(kEllipsisUTF16); + std::u16string text(UTF8ToUTF16("Hello, world!")); + std::u16string ellipsis(kEllipsisUTF16); // Eliding the end of a string should result in whitespace being removed // before the ellipsis in trim mode. @@ -572,8 +571,8 @@ TEST(TextEliderTest, StringSlicerWhitespace_Trim) { TEST(TextEliderTest, StringSlicer_ElideMiddle_MultipleWhitespace) { // Must store strings in variables (StringSlicer retains a reference to them). - base::string16 text(UTF8ToUTF16("Hello world!")); - base::string16 ellipsis(kEllipsisUTF16); + std::u16string text(UTF8ToUTF16("Hello world!")); + std::u16string ellipsis(kEllipsisUTF16); // Eliding the middle of a string should not result in whitespace being // removed around the ellipsis in default whitespace mode. @@ -624,32 +623,32 @@ TEST(TextEliderTest, StringSlicer_ElideMiddle_MultipleWhitespace) { 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 base::char16 kSurrogate[] = {0xD834, 0xDD1E, 0}; - base::string16 text(UTF8ToUTF16("abc") + kSurrogate + UTF8ToUTF16("xyz")); - base::string16 ellipsis(kEllipsisUTF16); + const char16_t kSurrogate[] = {0xD834, 0xDD1E, 0}; + std::u16string text(UTF8ToUTF16("abc") + kSurrogate + UTF8ToUTF16("xyz")); + std::u16string ellipsis(kEllipsisUTF16); StringSlicer slicer(text, ellipsis, false, false); // Cut surrogate on the right. Should round left and exclude the surrogate. - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(0, true)); + 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)); // Cut surrogate on the left. Should round right and exclude the surrogate. StringSlicer slicer_begin(text, ellipsis, false, true); - EXPECT_EQ(base::string16(kEllipsisUTF16) + UTF8ToUTF16("xyz"), + EXPECT_EQ(std::u16string(kEllipsisUTF16) + UTF8ToUTF16("xyz"), slicer_begin.CutString(4, true)); // Cut surrogate in the middle. Should round right and exclude the surrogate. - base::string16 short_text(UTF8ToUTF16("abc") + kSurrogate); + std::u16string short_text(UTF8ToUTF16("abc") + kSurrogate); StringSlicer slicer_mid(short_text, ellipsis, true, false); EXPECT_EQ(UTF8ToUTF16("a") + kEllipsisUTF16, slicer_mid.CutString(2, true)); // String that starts with a dangling trailing surrogate. - base::char16 dangling_trailing_chars[] = {kSurrogate[1], 0}; - base::string16 dangling_trailing_text(dangling_trailing_chars); + char16_t dangling_trailing_chars[] = {kSurrogate[1], 0}; + std::u16string dangling_trailing_text(dangling_trailing_chars); StringSlicer slicer_dangling_trailing(dangling_trailing_text, ellipsis, false, false); - EXPECT_EQ(base::string16(kEllipsisUTF16), + EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer_dangling_trailing.CutString(0, true)); EXPECT_EQ(dangling_trailing_text + kEllipsisUTF16, slicer_dangling_trailing.CutString(1, true)); @@ -661,10 +660,10 @@ 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 base::char16 kText[] = { - 'e', 0x301, 0x327, ' ', 'x', 0x20E3, ' ', 0x921, 0x93F, 0}; - base::string16 text(kText); - base::string16 ellipsis(kEllipsisUTF16); + const char16_t kText[] = {'e', 0x301, 0x327, ' ', 'x', + 0x20E3, ' ', 0x921, 0x93F, 0}; + std::u16string text(kText); + std::u16string ellipsis(kEllipsisUTF16); StringSlicer slicer(text, ellipsis, false, false); // Attempt to cut the string for all lengths. When a combining sequence is @@ -672,9 +671,9 @@ TEST(TextEliderTest, StringSlicerCombining) { // Whitespace is also cut adjacent to the ellipsis. // First sequence: - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(0, true)); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(1, true)); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(2, true)); + 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)); // Second sequence: EXPECT_EQ(text.substr(0, 3) + kEllipsisUTF16, slicer.CutString(4, true)); @@ -692,10 +691,10 @@ TEST(TextEliderTest, StringSlicerCombining) { slicer_mid.CutString(9, true)); // String that starts with a dangling combining mark. - base::char16 dangling_mark_chars[] = {text[1], 0}; - base::string16 dangling_mark_text(dangling_mark_chars); + 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(base::string16(kEllipsisUTF16), + EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer_dangling_mark.CutString(0, true)); EXPECT_EQ(dangling_mark_text + kEllipsisUTF16, slicer_dangling_mark.CutString(1, true)); @@ -706,22 +705,22 @@ 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 base::char16 kText[] = {0xD834, 0xDD1E, 0xD834, 0xDD6E, 0}; - base::string16 text(kText); - base::string16 ellipsis(kEllipsisUTF16); + const char16_t kText[] = {0xD834, 0xDD1E, 0xD834, 0xDD6E, 0}; + std::u16string text(kText); + std::u16string ellipsis(kEllipsisUTF16); 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(base::string16(kEllipsisUTF16), slicer.CutString(0, true)); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(1, true)); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(2, true)); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer.CutString(3, true)); + 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)); // Cut string in the middle. Should exclude the sequence. StringSlicer slicer_mid(text, ellipsis, true, false); - EXPECT_EQ(base::string16(kEllipsisUTF16), slicer_mid.CutString(4, true)); + EXPECT_EQ(std::u16string(kEllipsisUTF16), slicer_mid.CutString(4, true)); } TEST(TextEliderTest, ElideString) { @@ -744,7 +743,7 @@ TEST(TextEliderTest, ElideString) { { "Hello, my name is Tom", 100, false, "Hello, my name is Tom" } }; for (size_t i = 0; i < base::size(cases); ++i) { - base::string16 output; + std::u16string output; EXPECT_EQ(cases[i].result, ElideString(UTF8ToUTF16(cases[i].input), cases[i].max_len, &output)); @@ -755,7 +754,7 @@ TEST(TextEliderTest, ElideString) { TEST(TextEliderTest, ElideRectangleText) { const FontList font_list; const int line_height = font_list.GetHeight(); - const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list); + const float test_width = GetStringWidthF(u"Test", font_list); struct TestData { const char* input; @@ -792,7 +791,7 @@ TEST(TextEliderTest, ElideRectangleText) { }; for (size_t i = 0; i < base::size(cases); ++i) { - std::vector lines; + std::vector lines; EXPECT_EQ(cases[i].truncated_y ? INSUFFICIENT_SPACE_VERTICAL : 0, ElideRectangleText(UTF8ToUTF16(cases[i].input), font_list, @@ -801,8 +800,7 @@ TEST(TextEliderTest, ElideRectangleText) { TRUNCATE_LONG_WORDS, &lines)); if (cases[i].output) { - const std::string result = - UTF16ToUTF8(base::JoinString(lines, ASCIIToUTF16("|"))); + const std::string result = UTF16ToUTF8(base::JoinString(lines, u"|")); EXPECT_EQ(cases[i].output, result) << "Case " << i << " failed!"; } else { EXPECT_TRUE(lines.empty()) << "Case " << i << " failed!"; @@ -814,10 +812,10 @@ TEST(TextEliderTest, ElideRectangleTextFirstWordTruncated) { const FontList font_list; const int line_height = font_list.GetHeight(); - const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list); - const float tes_width = GetStringWidthF(ASCIIToUTF16("Tes"), font_list); + const float test_width = GetStringWidthF(u"Test", font_list); + const float tes_width = GetStringWidthF(u"Tes", font_list); - std::vector lines; + std::vector lines; auto result_for_width = [&](const char* input, float width) { lines.clear(); @@ -828,44 +826,44 @@ TEST(TextEliderTest, ElideRectangleTextFirstWordTruncated) { // Test base case. EXPECT_EQ(0, result_for_width("Test", test_width)); EXPECT_EQ(1u, lines.size()); - EXPECT_EQ(ASCIIToUTF16("Test"), lines[0]); + EXPECT_EQ(u"Test", lines[0]); // First word truncated. EXPECT_EQ(INSUFFICIENT_SPACE_FOR_FIRST_WORD, result_for_width("Test", tes_width)); EXPECT_EQ(2u, lines.size()); - EXPECT_EQ(ASCIIToUTF16("Tes"), lines[0]); - EXPECT_EQ(ASCIIToUTF16("t"), lines[1]); + 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)); EXPECT_EQ(4u, lines.size()); - EXPECT_EQ(ASCIIToUTF16("Tes"), lines[0]); - EXPECT_EQ(ASCIIToUTF16("t"), lines[1]); - EXPECT_EQ(ASCIIToUTF16("Tes"), lines[2]); - EXPECT_EQ(ASCIIToUTF16("t"), lines[3]); + EXPECT_EQ(u"Tes", lines[0]); + EXPECT_EQ(u"t", lines[1]); + EXPECT_EQ(u"Tes", lines[2]); + EXPECT_EQ(u"t", lines[3]); // Word truncated, but not the first. EXPECT_EQ(0, result_for_width("T Test", tes_width)); EXPECT_EQ(3u, lines.size()); - EXPECT_EQ(ASCIIToUTF16("T"), lines[0]); - EXPECT_EQ(ASCIIToUTF16("Tes"), lines[1]); - EXPECT_EQ(ASCIIToUTF16("t"), lines[2]); + 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(3u, lines.size()); - EXPECT_EQ(ASCIIToUTF16(""), lines[0]); - EXPECT_EQ(ASCIIToUTF16("Tes"), lines[1]); - EXPECT_EQ(ASCIIToUTF16("t"), lines[2]); + EXPECT_EQ(u"", lines[0]); + EXPECT_EQ(u"Tes", lines[1]); + EXPECT_EQ(u"t", lines[2]); } TEST(TextEliderTest, ElideRectangleTextPunctuation) { const FontList font_list; const int line_height = font_list.GetHeight(); - const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list); - const float test_t_width = GetStringWidthF(ASCIIToUTF16("Test T"), font_list); + const float test_width = GetStringWidthF(u"Test", font_list); + const float test_t_width = GetStringWidthF(u"Test T", font_list); constexpr int kResultMask = INSUFFICIENT_SPACE_HORIZONTAL | INSUFFICIENT_SPACE_VERTICAL; @@ -884,7 +882,7 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) { }; for (size_t i = 0; i < base::size(cases); ++i) { - std::vector lines; + std::vector lines; const WordWrapBehavior wrap_behavior = (cases[i].wrap_words ? WRAP_LONG_WORDS : TRUNCATE_LONG_WORDS); EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0, @@ -894,8 +892,7 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) { &lines) & kResultMask); if (cases[i].output) { - const std::string result = - UTF16ToUTF8(base::JoinString(lines, base::ASCIIToUTF16("|"))); + const std::string result = UTF16ToUTF8(base::JoinString(lines, u"|")); EXPECT_EQ(cases[i].output, result) << "Case " << i << " failed!"; } else { EXPECT_TRUE(lines.empty()) << "Case " << i << " failed!"; @@ -906,10 +903,10 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) { TEST(TextEliderTest, ElideRectangleTextLongWords) { const FontList font_list; const int kAvailableHeight = 1000; - const base::string16 kElidedTesting = + const std::u16string kElidedTesting = UTF8ToUTF16(std::string("Tes") + kEllipsis); const float elided_width = GetStringWidthF(kElidedTesting, font_list); - const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list); + const float test_width = GetStringWidthF(u"Test", font_list); constexpr int kResultMask = INSUFFICIENT_SPACE_HORIZONTAL | INSUFFICIENT_SPACE_VERTICAL; @@ -950,7 +947,7 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) { }; for (size_t i = 0; i < base::size(cases); ++i) { - std::vector lines; + std::vector lines; EXPECT_EQ( cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0, ElideRectangleText(UTF8ToUTF16(cases[i].input), font_list, @@ -959,8 +956,7 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) { kResultMask); std::string expected_output(cases[i].output); base::ReplaceSubstringsAfterOffset(&expected_output, 0, "...", kEllipsis); - const std::string result = - UTF16ToUTF8(base::JoinString(lines, base::ASCIIToUTF16("|"))); + const std::string result = UTF16ToUTF8(base::JoinString(lines, u"|")); EXPECT_EQ(expected_output, result) << "Case " << i << " failed!"; } } @@ -979,7 +975,7 @@ TEST(TextEliderTest, ElideRectangleTextCheckLineWidth) { const float kAvailableWidth = 235; const int kAvailableHeight = 1000; const char text[] = "that Russian place we used to go to after fencing"; - std::vector lines; + std::vector lines; EXPECT_EQ(0, ElideRectangleText(UTF8ToUTF16(text), font_list, kAvailableWidth, @@ -1081,7 +1077,7 @@ TEST(TextEliderTest, ElideRectangleString) { { "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" }, }; - base::string16 output; + std::u16string output; for (size_t i = 0; i < base::size(cases); ++i) { EXPECT_EQ(cases[i].result, ElideRectangleString(UTF8ToUTF16(cases[i].input), @@ -1163,7 +1159,7 @@ TEST(TextEliderTest, ElideRectangleStringNotStrict) { { "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" }, }; - base::string16 output; + std::u16string output; for (size_t i = 0; i < base::size(cases); ++i) { EXPECT_EQ(cases[i].result, ElideRectangleString(UTF8ToUTF16(cases[i].input), @@ -1175,17 +1171,17 @@ TEST(TextEliderTest, ElideRectangleStringNotStrict) { TEST(TextEliderTest, ElideRectangleWide16) { // Two greek words separated by space. - const base::string16 str(WideToUTF16( - L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9" - L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2")); - const base::string16 out1(WideToUTF16( - L"\x03a0\x03b1\x03b3\x03ba\n" - L"\x03cc\x03c3\x03bc\x03b9\n" - L"...")); - const base::string16 out2(WideToUTF16( - L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9\x03bf\x03c2\x0020\n" - L"\x0399\x03c3\x03c4\x03cc\x03c2")); - base::string16 output; + 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"); + std::u16string output; EXPECT_TRUE(ElideRectangleString(str, 2, 4, true, &output)); EXPECT_EQ(out1, output); EXPECT_FALSE(ElideRectangleString(str, 2, 12, true, &output)); @@ -1194,23 +1190,23 @@ TEST(TextEliderTest, ElideRectangleWide16) { TEST(TextEliderTest, ElideRectangleWide32) { // Four U+1D49C MATHEMATICAL SCRIPT CAPITAL A followed by space "aaaaa". - const base::string16 str(UTF8ToUTF16( + const std::u16string str(UTF8ToUTF16( "\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C" " aaaaa")); - const base::string16 out(UTF8ToUTF16( - "\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\n" - "\xF0\x9D\x92\x9C \naaa\n...")); - base::string16 output; + const std::u16string out( + UTF8ToUTF16("\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\n" + "\xF0\x9D\x92\x9C \naaa\n...")); + std::u16string output; EXPECT_TRUE(ElideRectangleString(str, 3, 3, true, &output)); EXPECT_EQ(out, output); } TEST(TextEliderTest, TruncateString) { - base::string16 str = ASCIIToUTF16("fooooey bxxxar baz "); + std::u16string str = u"fooooey bxxxar baz "; // Test breaking at character 0. - EXPECT_EQ(base::string16(), TruncateString(str, 0, WORD_BREAK)); - EXPECT_EQ(base::string16(), TruncateString(str, 0, CHARACTER_BREAK)); + EXPECT_EQ(std::u16string(), TruncateString(str, 0, WORD_BREAK)); + EXPECT_EQ(std::u16string(), TruncateString(str, 0, CHARACTER_BREAK)); // Test breaking at character 1. EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str, 1, WORD_BREAK))); @@ -1254,7 +1250,7 @@ TEST(TextEliderTest, TruncateString) { // Tests of strings with leading whitespace: - base::string16 str2 = ASCIIToUTF16(" foo"); + std::u16string str2 = u" foo"; // Test breaking in leading whitespace. EXPECT_EQ(L"\x2026", UTF16ToWide(TruncateString(str2, 2, WORD_BREAK))); diff --git a/chromium/ui/gfx/text_utils.cc b/chromium/ui/gfx/text_utils.cc index 58a002da7c3..2e73a65fc7a 100644 --- a/chromium/ui/gfx/text_utils.cc +++ b/chromium/ui/gfx/text_utils.cc @@ -22,9 +22,9 @@ using base::i18n::UTF16CharIterator; namespace { -constexpr base::char16 kAcceleratorChar = '&'; -constexpr base::char16 kOpenParenthesisChar = '('; -constexpr base::char16 kCloseParenthesisChar = ')'; +constexpr char16_t kAcceleratorChar = '&'; +constexpr char16_t kOpenParenthesisChar = '('; +constexpr char16_t kCloseParenthesisChar = ')'; // Returns true if the specified character must be elided from a string. // Examples are combining marks and whitespace. @@ -43,15 +43,15 @@ bool IsSpace(UChar32 c) { char_type == U_PARAGRAPH_SEPARATOR || char_type == U_CONTROL_CHAR; } -base::string16 RemoveAcceleratorChar(bool full_removal, - const base::string16& s, +std::u16string RemoveAcceleratorChar(bool full_removal, + const std::u16string& s, int* accelerated_char_pos, int* accelerated_char_span) { bool escaped = false; ptrdiff_t last_char_pos = -1; int last_char_span = 0; UTF16CharIterator chars(s); - base::string16 accelerator_removed; + std::u16string accelerator_removed; // The states of a state machine looking for a CJK-style accelerator (i.e. // "(&x)"). |cjk_state| proceeds up from |kFoundNothing| through these states, @@ -115,18 +115,18 @@ base::string16 RemoveAcceleratorChar(bool full_removal, } // namespace -base::string16 LocateAndRemoveAcceleratorChar(const base::string16& s, +std::u16string LocateAndRemoveAcceleratorChar(const std::u16string& s, int* accelerated_char_pos, int* accelerated_char_span) { return RemoveAcceleratorChar(false, s, accelerated_char_pos, accelerated_char_span); } -base::string16 RemoveAccelerator(const base::string16& s) { +std::u16string RemoveAccelerator(const std::u16string& s) { return RemoveAcceleratorChar(true, s, nullptr, nullptr); } -size_t FindValidBoundaryBefore(const base::string16& text, +size_t FindValidBoundaryBefore(const std::u16string& text, size_t index, bool trim_whitespace) { UTF16CharIterator it = UTF16CharIterator::LowerBound(text, index); @@ -145,7 +145,7 @@ size_t FindValidBoundaryBefore(const base::string16& text, return it.array_pos(); } -size_t FindValidBoundaryAfter(const base::string16& text, +size_t FindValidBoundaryAfter(const std::u16string& text, size_t index, bool trim_whitespace) { UTF16CharIterator it = UTF16CharIterator::UpperBound(text, index); @@ -177,7 +177,7 @@ HorizontalAlignment MaybeFlipForRTL(HorizontalAlignment alignment) { return alignment; } -Size GetStringSize(const base::string16& text, const FontList& font_list) { +Size GetStringSize(const std::u16string& text, const FontList& font_list) { return Size(GetStringWidth(text, font_list), font_list.GetHeight()); } diff --git a/chromium/ui/gfx/text_utils.h b/chromium/ui/gfx/text_utils.h index d1ca32810de..b25a0013d22 100644 --- a/chromium/ui/gfx/text_utils.h +++ b/chromium/ui/gfx/text_utils.h @@ -7,7 +7,8 @@ #include -#include "base/strings/string16.h" +#include + #include "ui/gfx/gfx_export.h" #include "ui/gfx/text_constants.h" @@ -25,8 +26,8 @@ class Size; // |accelerated_char_pos| and |accelerated_char_span| will be set to the index // and span of the last accelerated character, respectively, or -1 and 0 if // there was none. -GFX_EXPORT base::string16 LocateAndRemoveAcceleratorChar( - const base::string16& s, +GFX_EXPORT std::u16string LocateAndRemoveAcceleratorChar( + const std::u16string& s, int* accelerated_char_pos, int* accelerated_char_span); @@ -37,33 +38,33 @@ GFX_EXPORT base::string16 LocateAndRemoveAcceleratorChar( // Single accelerator chars ('&') will be stripped from the string. Double // accelerator chars ('&&') will be converted to a single '&'. CJK language // accelerators, specified as "(&x)", will be entirely removed too. -GFX_EXPORT base::string16 RemoveAccelerator(const base::string16& s); +GFX_EXPORT std::u16string RemoveAccelerator(const std::u16string& s); // Returns the number of horizontal pixels needed to display the specified // |text| with |font_list|. |typesetter| indicates where the text will be // displayed. -GFX_EXPORT int GetStringWidth(const base::string16& text, +GFX_EXPORT int GetStringWidth(const std::u16string& text, const FontList& font_list); // Returns the size required to render |text| in |font_list|. This includes all // leading space, descender area, etc. even if the text to render does not // contain characters with ascenders or descenders. -GFX_EXPORT Size GetStringSize(const base::string16& text, +GFX_EXPORT Size GetStringSize(const std::u16string& text, const FontList& font_list); // This is same as GetStringWidth except that fractional width is returned. -GFX_EXPORT float GetStringWidthF(const base::string16& text, +GFX_EXPORT float GetStringWidthF(const std::u16string& text, const FontList& font_list); // Returns a valid cut boundary at or before |index|. The surrogate pair and // combining characters should not be separated. -GFX_EXPORT size_t FindValidBoundaryBefore(const base::string16& text, +GFX_EXPORT size_t FindValidBoundaryBefore(const std::u16string& text, size_t index, bool trim_whitespace = false); // Returns a valid cut boundary at or after |index|. The surrogate pair and // combining characters should not be separated. -GFX_EXPORT size_t FindValidBoundaryAfter(const base::string16& text, +GFX_EXPORT size_t FindValidBoundaryAfter(const std::u16string& text, size_t index, bool trim_whitespace = false); diff --git a/chromium/ui/gfx/text_utils_ios.mm b/chromium/ui/gfx/text_utils_ios.mm index 1c50b7f8722..1f7631601d7 100644 --- a/chromium/ui/gfx/text_utils_ios.mm +++ b/chromium/ui/gfx/text_utils_ios.mm @@ -13,11 +13,11 @@ namespace gfx { -int GetStringWidth(const base::string16& text, const FontList& font_list) { +int GetStringWidth(const std::u16string& text, const FontList& font_list) { return std::ceil(GetStringWidthF(text, font_list)); } -float GetStringWidthF(const base::string16& text, const FontList& font_list) { +float GetStringWidthF(const std::u16string& text, const FontList& font_list) { NSString* ns_text = base::SysUTF16ToNSString(text); NativeFont native_font = font_list.GetPrimaryFont().GetNativeFont(); NSDictionary* attributes = @{NSFontAttributeName : native_font}; diff --git a/chromium/ui/gfx/text_utils_skia.cc b/chromium/ui/gfx/text_utils_skia.cc index 4ef0c234897..2c8e96c3ab7 100644 --- a/chromium/ui/gfx/text_utils_skia.cc +++ b/chromium/ui/gfx/text_utils_skia.cc @@ -8,11 +8,11 @@ namespace gfx { -int GetStringWidth(const base::string16& text, const FontList& font_list) { +int GetStringWidth(const std::u16string& text, const FontList& font_list) { return Canvas::GetStringWidth(text, font_list); } -float GetStringWidthF(const base::string16& text, const FontList& font_list) { +float GetStringWidthF(const std::u16string& text, const FontList& font_list) { return Canvas::GetStringWidthF(text, font_list); } diff --git a/chromium/ui/gfx/text_utils_unittest.cc b/chromium/ui/gfx/text_utils_unittest.cc index 12df151394e..7d7a4d74b73 100644 --- a/chromium/ui/gfx/text_utils_unittest.cc +++ b/chromium/ui/gfx/text_utils_unittest.cc @@ -23,24 +23,23 @@ namespace { TEST(TextUtilsTest, GetStringWidth) { FontList font_list; - EXPECT_EQ(GetStringWidth(base::string16(), font_list), 0); - EXPECT_GT(GetStringWidth(base::ASCIIToUTF16("a"), font_list), - GetStringWidth(base::string16(), font_list)); - EXPECT_GT(GetStringWidth(base::ASCIIToUTF16("ab"), font_list), - GetStringWidth(base::ASCIIToUTF16("a"), font_list)); - EXPECT_GT(GetStringWidth(base::ASCIIToUTF16("abc"), font_list), - GetStringWidth(base::ASCIIToUTF16("ab"), font_list)); + EXPECT_EQ(GetStringWidth(std::u16string(), font_list), 0); + EXPECT_GT(GetStringWidth(u"a", font_list), + GetStringWidth(std::u16string(), font_list)); + EXPECT_GT(GetStringWidth(u"ab", font_list), GetStringWidth(u"a", font_list)); + EXPECT_GT(GetStringWidth(u"abc", font_list), + GetStringWidth(u"ab", font_list)); } TEST(TextUtilsTest, GetStringSize) { - std::vector strings{ - base::string16(), - base::ASCIIToUTF16("a"), - base::ASCIIToUTF16("abc"), + std::vector strings{ + std::u16string(), + u"a", + u"abc", }; FontList font_list; - for (base::string16 string : strings) { + for (std::u16string string : strings) { gfx::Size size = GetStringSize(string, font_list); EXPECT_EQ(GetStringWidth(string, font_list), size.width()) << " input string is \"" << string << "\""; @@ -193,10 +192,10 @@ TEST_P(RemoveAcceleratorCharTest, RemoveAcceleratorChar) { RemoveAcceleratorCharData data = GetParam(); int accelerated_char_pos; int accelerated_char_span; - base::string16 result_locate_and_strip = LocateAndRemoveAcceleratorChar( + std::u16string result_locate_and_strip = LocateAndRemoveAcceleratorChar( base::UTF8ToUTF16(data.input), &accelerated_char_pos, &accelerated_char_span); - base::string16 result_full_strip = + std::u16string result_full_strip = RemoveAccelerator(base::UTF8ToUTF16(data.input)); EXPECT_EQ(result_locate_and_strip, base::UTF8ToUTF16(data.output_locate_and_strip)); @@ -276,8 +275,8 @@ INSTANTIATE_TEST_SUITE_P( TEST_P(FindValidBoundaryBeforeTest, FindValidBoundaryBefore) { FindValidBoundaryData data = GetParam(); - const base::string16::const_pointer input = - reinterpret_cast(data.input); + const std::u16string::const_pointer input = + reinterpret_cast(data.input); DLOG(INFO) << input; size_t result = FindValidBoundaryBefore(input, data.index_in, data.trim_whitespace); @@ -349,8 +348,8 @@ INSTANTIATE_TEST_SUITE_P( TEST_P(FindValidBoundaryAfterTest, FindValidBoundaryAfter) { FindValidBoundaryData data = GetParam(); - const base::string16::const_pointer input = - reinterpret_cast(data.input); + const std::u16string::const_pointer input = + reinterpret_cast(data.input); size_t result = FindValidBoundaryAfter(input, data.index_in, data.trim_whitespace); EXPECT_EQ(data.index_out, result); diff --git a/chromium/ui/gfx/utf16_indexing.cc b/chromium/ui/gfx/utf16_indexing.cc index 4515ff6a8bf..164db80b3b1 100644 --- a/chromium/ui/gfx/utf16_indexing.cc +++ b/chromium/ui/gfx/utf16_indexing.cc @@ -9,12 +9,12 @@ namespace gfx { -bool IsValidCodePointIndex(const base::string16& s, size_t index) { +bool IsValidCodePointIndex(const std::u16string& s, size_t index) { return index == 0 || index == s.length() || !(CBU16_IS_TRAIL(s[index]) && CBU16_IS_LEAD(s[index - 1])); } -ptrdiff_t UTF16IndexToOffset(const base::string16& s, size_t base, size_t pos) { +ptrdiff_t UTF16IndexToOffset(const std::u16string& s, size_t base, size_t pos) { // The indices point between UTF-16 words (range 0 to s.length() inclusive). // In order to consistently handle indices that point to the middle of a // surrogate pair, we count the first word in that surrogate pair and not @@ -30,7 +30,7 @@ ptrdiff_t UTF16IndexToOffset(const base::string16& s, size_t base, size_t pos) { return delta; } -size_t UTF16OffsetToIndex(const base::string16& s, +size_t UTF16OffsetToIndex(const std::u16string& s, size_t base, ptrdiff_t offset) { DCHECK_LE(base, s.length()); diff --git a/chromium/ui/gfx/utf16_indexing.h b/chromium/ui/gfx/utf16_indexing.h index 779109dd84d..4831c412302 100644 --- a/chromium/ui/gfx/utf16_indexing.h +++ b/chromium/ui/gfx/utf16_indexing.h @@ -7,14 +7,15 @@ #include -#include "base/strings/string16.h" +#include + #include "ui/gfx/gfx_export.h" namespace gfx { // Returns false if s[index-1] is a high surrogate and s[index] is a low // surrogate, true otherwise. -GFX_EXPORT bool IsValidCodePointIndex(const base::string16& s, size_t index); +GFX_EXPORT bool IsValidCodePointIndex(const std::u16string& s, size_t index); // |UTF16IndexToOffset| returns the number of code points between |base| and // |pos| in the given string. |UTF16OffsetToIndex| returns the index that is @@ -39,10 +40,10 @@ GFX_EXPORT bool IsValidCodePointIndex(const base::string16& s, size_t index); // Always, // UTF16IndexToOffset(s, base, UTF16OffsetToIndex(s, base, ofs)) == ofs // UTF16IndexToOffset(s, i, j) == -UTF16IndexToOffset(s, j, i) -GFX_EXPORT ptrdiff_t UTF16IndexToOffset(const base::string16& s, +GFX_EXPORT ptrdiff_t UTF16IndexToOffset(const std::u16string& s, size_t base, size_t pos); -GFX_EXPORT size_t UTF16OffsetToIndex(const base::string16& s, +GFX_EXPORT size_t UTF16OffsetToIndex(const std::u16string& s, size_t base, ptrdiff_t offset); diff --git a/chromium/ui/gfx/utf16_indexing_unittest.cc b/chromium/ui/gfx/utf16_indexing_unittest.cc index 55ef3cbd9d5..289fd449f02 100644 --- a/chromium/ui/gfx/utf16_indexing_unittest.cc +++ b/chromium/ui/gfx/utf16_indexing_unittest.cc @@ -11,9 +11,8 @@ namespace gfx { TEST(UTF16IndexingTest, IndexOffsetConversions) { // Valid surrogate pair surrounded by unpaired surrogates - const base::char16 foo[] = - {0xDC00, 0xD800, 0xD800, 0xDFFF, 0xDFFF, 0xDBFF, 0}; - const base::string16 s(foo); + const char16_t foo[] = {0xDC00, 0xD800, 0xD800, 0xDFFF, 0xDFFF, 0xDBFF, 0}; + const std::u16string s(foo); const size_t the_invalid_index = 3; for (size_t i = 0; i <= s.length(); ++i) EXPECT_EQ(i != the_invalid_index, IsValidCodePointIndex(s, i)); diff --git a/chromium/ui/gfx/win/hwnd_util.cc b/chromium/ui/gfx/win/hwnd_util.cc index d5586a9fae0..286b766a2a3 100644 --- a/chromium/ui/gfx/win/hwnd_util.cc +++ b/chromium/ui/gfx/win/hwnd_util.cc @@ -6,7 +6,7 @@ #include -#include "base/debug/alias.h" +#include "base/debug/gdi_debug_util_win.h" #include "base/logging.h" #include "base/notreached.h" #include "base/strings/string_util.h" @@ -54,24 +54,6 @@ void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) { // Don't inline these functions so they show up in crash reports. -NOINLINE void CrashOutOfMemory(DWORD last_error) { - // Record Graphics Device Interface (GDI) object counts so they are visible in - // the crash's minidump. By default, GDI and USER handles are limited to - // 10,000 each per process and 65,535 each globally, exceeding which typically - // indicates a leak of GDI resources. - const HANDLE process = ::GetCurrentProcess(); - DWORD num_process_gdi_handles = ::GetGuiResources(process, GR_GDIOBJECTS); - DWORD num_process_user_handles = ::GetGuiResources(process, GR_USEROBJECTS); - DWORD num_global_gdi_handles = ::GetGuiResources(GR_GLOBAL, GR_GDIOBJECTS); - DWORD num_global_user_handles = ::GetGuiResources(GR_GLOBAL, GR_USEROBJECTS); - base::debug::Alias(&num_process_gdi_handles); - base::debug::Alias(&num_process_user_handles); - base::debug::Alias(&num_global_gdi_handles); - base::debug::Alias(&num_global_user_handles); - - LOG(FATAL) << last_error; -} - NOINLINE void CrashAccessDenied(DWORD last_error) { LOG(FATAL) << last_error; } @@ -204,7 +186,7 @@ void CheckWindowCreated(HWND hwnd, DWORD last_error) { if (!hwnd) { switch (last_error) { case ERROR_NOT_ENOUGH_MEMORY: - CrashOutOfMemory(last_error); + base::debug::CollectGDIUsageAndDie(); break; case ERROR_ACCESS_DENIED: CrashAccessDenied(last_error); diff --git a/chromium/ui/gfx/win/msg_util.h b/chromium/ui/gfx/win/msg_util.h index f75d7ac21af..7c6b42b2314 100644 --- a/chromium/ui/gfx/win/msg_util.h +++ b/chromium/ui/gfx/win/msg_util.h @@ -5,8 +5,8 @@ #ifndef UI_GFX_WIN_MSG_UTIL_H_ #define UI_GFX_WIN_MSG_UTIL_H_ -#include "base/logging.h" #include "base/memory/weak_ptr.h" +#include "base/notreached.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" diff --git a/chromium/ui/gfx/x/connection.cc b/chromium/ui/gfx/x/connection.cc index 3643dba8065..b38f0696c8d 100644 --- a/chromium/ui/gfx/x/connection.cc +++ b/chromium/ui/gfx/x/connection.cc @@ -8,13 +8,13 @@ #include #include +#include #include "base/auto_reset.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" #include "base/no_destructor.h" -#include "base/strings/string16.h" #include "base/threading/thread_local.h" #include "base/trace_event/trace_event.h" #include "ui/gfx/x/bigreq.h" @@ -128,7 +128,8 @@ Connection::Connection(const std::string& address) DCHECK(connection_); if (Ready()) { auto buf = ReadBuffer(base::MakeRefCounted( - xcb_get_setup(XcbConnection()))); + xcb_get_setup(XcbConnection())), + true); setup_ = Read(&buf); default_screen_ = &setup_.roots[DefaultScreenId()]; InitRootDepthAndVisual(); diff --git a/chromium/ui/gfx/x/x11_atom_cache.cc b/chromium/ui/gfx/x/x11_atom_cache.cc index db030cc9bd3..31397f5711e 100644 --- a/chromium/ui/gfx/x/x11_atom_cache.cc +++ b/chromium/ui/gfx/x/x11_atom_cache.cc @@ -134,6 +134,7 @@ constexpr const char* kAtomsToCache[] = { "_NET_WM_USER_TIME", "_NET_WM_WINDOW_OPACITY", "_NET_WM_WINDOW_TYPE", + "_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_DND", "_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_NORMAL", @@ -163,6 +164,9 @@ constexpr const char* kAtomsToCache[] = { "text/rtf", "text/uri-list", "text/x-moz-url", + "xwayland-pointer", + "xwayland-keyboard", + "xwayland-touch", }; constexpr int kCacheCount = base::size(kAtomsToCache); diff --git a/chromium/ui/gfx/x/xproto_types.cc b/chromium/ui/gfx/x/xproto_types.cc index cbc3506c608..5546cd81cb3 100644 --- a/chromium/ui/gfx/x/xproto_types.cc +++ b/chromium/ui/gfx/x/xproto_types.cc @@ -25,8 +25,15 @@ struct ReplyHeader { } // namespace -ReadBuffer::ReadBuffer(scoped_refptr data) +ReadBuffer::ReadBuffer(scoped_refptr data, + bool setup_message) : data(data) { + // X connection setup uses a special reply without the standard header, see: + // https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html#server_response + // Don't try to parse it like a normal reply. + if (setup_message) + return; + const auto* reply_header = reinterpret_cast(data->data()); // Only replies can have FDs, not events or errors. diff --git a/chromium/ui/gfx/x/xproto_types.h b/chromium/ui/gfx/x/xproto_types.h index f591363f241..cab307a08fb 100644 --- a/chromium/ui/gfx/x/xproto_types.h +++ b/chromium/ui/gfx/x/xproto_types.h @@ -36,7 +36,8 @@ void VerifyAlignment(T* t, size_t offset) { // Wraps data read from the connection. struct COMPONENT_EXPORT(X11) ReadBuffer { - explicit ReadBuffer(scoped_refptr data); + explicit ReadBuffer(scoped_refptr data, + bool setup_message = false); ReadBuffer(const ReadBuffer&) = delete; ReadBuffer(ReadBuffer&&); diff --git a/chromium/ui/gl/BUILD.gn b/chromium/ui/gl/BUILD.gn index b815fda06ed..23a0ee6130c 100644 --- a/chromium/ui/gl/BUILD.gn +++ b/chromium/ui/gl/BUILD.gn @@ -305,6 +305,7 @@ component("gl") { "child_window_win.h", "dc_layer_tree.cc", "dc_layer_tree.h", + "delegated_ink_point_renderer_gpu.h", "direct_composition_child_surface_win.cc", "direct_composition_child_surface_win.h", "direct_composition_surface_win.cc", @@ -336,6 +337,7 @@ component("gl") { "/DELAYLOAD:dwmapi.dll", "/DELAYLOAD:dxgi.dll", ] + deps += [ "//media/base/win:media_foundation_util" ] assert(use_egl) data_deps += [ diff --git a/chromium/ui/gl/DEPS b/chromium/ui/gl/DEPS index 2f1f2450dd0..e0adf27d88e 100644 --- a/chromium/ui/gl/DEPS +++ b/chromium/ui/gl/DEPS @@ -34,4 +34,7 @@ specific_include_rules = { "hdr_metadata_helper_win_unittest.cc": [ "+media/base/win/d3d11_mocks.h", ], + "swap_chain_presenter.cc": [ + "+media/base/win/mf_helpers.h" + ], } diff --git a/chromium/ui/gl/angle_platform_impl.cc b/chromium/ui/gl/angle_platform_impl.cc index 5401759f349..8825241afd0 100644 --- a/chromium/ui/gl/angle_platform_impl.cc +++ b/chromium/ui/gl/angle_platform_impl.cc @@ -12,6 +12,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_functions.h" #include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/trace_event/trace_event.h" #include "third_party/angle/include/platform/PlatformMethods.h" diff --git a/chromium/ui/gl/child_window_win.cc b/chromium/ui/gl/child_window_win.cc index 3b9654af9ce..573a2686c33 100644 --- a/chromium/ui/gl/child_window_win.cc +++ b/chromium/ui/gl/child_window_win.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/compiler_specific.h" #include "base/debug/alias.h" +#include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_pump_type.h" #include "base/win/wrapped_window_proc.h" diff --git a/chromium/ui/gl/dc_layer_tree.cc b/chromium/ui/gl/dc_layer_tree.cc index 760dc2ffb55..8a8bd381997 100644 --- a/chromium/ui/gl/dc_layer_tree.cc +++ b/chromium/ui/gl/dc_layer_tree.cc @@ -6,44 +6,21 @@ #include "ui/gl/dc_layer_tree.h" +#include + +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "base/trace_event/trace_event.h" #include "ui/gl/direct_composition_child_surface_win.h" #include "ui/gl/direct_composition_surface_win.h" #include "ui/gl/swap_chain_presenter.h" -// Required for SFINAE to check if these Win10 types exist. -struct IDCompositionInkTrailDevice; - namespace gl { namespace { bool SizeContains(const gfx::Size& a, const gfx::Size& b) { return gfx::Rect(a).Contains(gfx::Rect(b)); } -// SFINAE used to enable building before Delegated Ink types are available in -// the Win10 SDK. -// TODO(1171374) : Remove this when the types are available in the Win10 SDK. -template -struct DelegatedInk { - public: - static bool IsSupported( - const Microsoft::WRL::ComPtr& dcomp_device) { - return false; - } -}; - -template -struct DelegatedInk { - public: - static bool IsSupported( - const Microsoft::WRL::ComPtr& dcomp_device) { - Microsoft::WRL::ComPtr ink_trail_device; - HRESULT hr = dcomp_device.As(&ink_trail_device); - return hr == S_OK; - } -}; - } // namespace VideoProcessorWrapper::VideoProcessorWrapper() = default; @@ -56,7 +33,12 @@ VideoProcessorWrapper& VideoProcessorWrapper::operator=( 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) {} + disable_vp_scaling_(disable_vp_scaling), + ink_renderer_( + std::make_unique< + DelegatedInkPointRendererGpu>()) { +} DCLayerTree::~DCLayerTree() = default; @@ -206,7 +188,7 @@ bool DCLayerTree::CommitAndClearPendingOverlays( DirectCompositionChildSurfaceWin* root_surface) { TRACE_EVENT1("gpu", "DCLayerTree::CommitAndClearPendingOverlays", "num_pending_overlays", pending_overlays_.size()); - DCHECK(!needs_rebuild_visual_tree_); + DCHECK(!needs_rebuild_visual_tree_ || ink_renderer_->HasBeenInitialized()); bool needs_commit = false; // Check if root surface visual needs a commit first. if (!root_surface_visual_) { @@ -272,7 +254,9 @@ bool DCLayerTree::CommitAndClearPendingOverlays( // Rebuild visual tree and commit if any visual changed. // Note: needs_rebuild_visual_tree_ might be set in this function and in - // SetNeedsRebuildVisualTree() during video_swap_chain->PresentToSwapChain() + // SetNeedsRebuildVisualTree() during video_swap_chain->PresentToSwapChain(). + // Can also be set in DCLayerTree::SetDelegatedInkTrailStartPoint to add a + // delegated ink visual into the tree. if (needs_rebuild_visual_tree_) { TRACE_EVENT0( "gpu", "DCLayerTree::CommitAndClearPendingOverlays::ReBuildVisualTree"); @@ -300,6 +284,19 @@ bool DCLayerTree::CommitAndClearPendingOverlays( IDCompositionVisual2* visual = video_swap_chains_[i]->visual().Get(); dcomp_root_visual_->AddVisual(visual, FALSE, nullptr); } + + // Only add the ink visual to the tree if it has already been initialized. + // It will only have been initialized if delegated ink has been used, so + // this ensures the visual is only added when it is needed. The ink renderer + // must be updated so that if the root swap chain or dcomp device have + // changed the ink visual and delegated ink object can be updated + // accordingly. + if (ink_renderer_->HasBeenInitialized()) { + // Reinitialize the ink renderer in case the root swap chain or dcomp + // device changed since initialization. + if (InitializeInkRenderer()) + AddDelegatedInkVisualToTree(); + } needs_commit = true; } @@ -328,7 +325,35 @@ void DCLayerTree::SetFrameRate(float frame_rate) { } bool DCLayerTree::SupportsDelegatedInk() { - return DelegatedInk::IsSupported(dcomp_device_); + return ink_renderer_->DelegatedInkIsSupported(dcomp_device_); +} + +bool DCLayerTree::InitializeInkRenderer() { + return ink_renderer_->Initialize(dcomp_device_, root_swap_chain_); +} + +void DCLayerTree::AddDelegatedInkVisualToTree() { + DCHECK(SupportsDelegatedInk()); + DCHECK(ink_renderer_->HasBeenInitialized()); + + root_surface_visual_->AddVisual(ink_renderer_->GetInkVisual(), FALSE, + nullptr); +} + +void DCLayerTree::SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) { + DCHECK(SupportsDelegatedInk()); + + if (!ink_renderer_->HasBeenInitialized()) { + if (!InitializeInkRenderer()) + return; + // This ensures that the delegated ink visual is added to the tree after + // the root visual is created, during + // DCLayerTree::CommitAndClearPendingOverlays + needs_rebuild_visual_tree_ = true; + } + + ink_renderer_->SetDelegatedInkTrailStartPoint(std::move(metadata)); } } // namespace gl diff --git a/chromium/ui/gl/dc_layer_tree.h b/chromium/ui/gl/dc_layer_tree.h index ec7d925d928..0bcfc41d511 100644 --- a/chromium/ui/gl/dc_layer_tree.h +++ b/chromium/ui/gl/dc_layer_tree.h @@ -16,8 +16,13 @@ #include "ui/gfx/color_space_win.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/dc_renderer_layer_params.h" +#include "ui/gl/delegated_ink_point_renderer_gpu.h" #include "ui/gl/hdr_metadata_helper_win.h" +namespace gfx { +class DelegatedInkMetadata; +} // namespace gfx + namespace gl { class DirectCompositionChildSurfaceWin; @@ -109,7 +114,20 @@ class DCLayerTree { bool SupportsDelegatedInk(); + void SetDelegatedInkTrailStartPoint( + std::unique_ptr); + 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 + // delegated ink API is used. After that, it can also be added anytime the + // visual tree is rebuilt. + void AddDelegatedInkVisualToTree(); + + // The ink renderer must be initialized before an OS API is used in order to + // set up the delegated ink visual and delegated ink trail object. + bool InitializeInkRenderer(); + const bool disable_nv12_dynamic_textures_; const bool disable_vp_scaling_; @@ -154,6 +172,14 @@ class DCLayerTree { // dealing with hdr metadata std::unique_ptr hdr_metadata_helper_; + // Renderer for drawing delegated ink trails using OS APIs. This is created + // 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> + ink_renderer_; + DISALLOW_COPY_AND_ASSIGN(DCLayerTree); }; diff --git a/chromium/ui/gl/delegated_ink_point_renderer_gpu.h b/chromium/ui/gl/delegated_ink_point_renderer_gpu.h new file mode 100644 index 00000000000..459dfc734ae --- /dev/null +++ b/chromium/ui/gl/delegated_ink_point_renderer_gpu.h @@ -0,0 +1,190 @@ +// 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_GL_DELEGATED_INK_POINT_RENDERER_GPU_H_ +#define UI_GL_DELEGATED_INK_POINT_RENDERER_GPU_H_ + +#include +#include + +#include +#include + +#include "base/trace_event/trace_event.h" +#include "ui/gfx/delegated_ink_metadata.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; + +namespace gl { + +// TODO(1171374): Remove this class and remove templates when the types are +// available in the Win10 SDK. +template +class DelegatedInkPointRendererGpu { + public: + DelegatedInkPointRendererGpu() = default; + bool Initialize( + const Microsoft::WRL::ComPtr& dcomp_device, + const Microsoft::WRL::ComPtr& root_swap_chain) { + NOTREACHED(); + return false; + } + + bool HasBeenInitialized() const { return false; } + + IDCompositionVisual* GetInkVisual() const { + NOTREACHED(); + return nullptr; + } + + bool DelegatedInkIsSupported( + const Microsoft::WRL::ComPtr& dcomp_device) const { + return false; + } + + void SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) { + NOTREACHED(); + } +}; + +// This class will call the OS delegated ink trail APIs when they become +// available. Currently using SFINAE to land changes ahead of the SDK, so that +// the OS APIs can be used immediately. +// TODO(1171374): Remove the template SFINAE. +// +// On construction, this class will create a new visual for the visual tree with +// an IDCompositionDelegatedInk object as the contents. This will be added as +// a child of the root surface visual in the tree, and the trail will be drawn +// to it. It is a child of the root surface visual because this visual contains +// the swapchain, and there will be no transforms applied to the delegated ink +// 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 +class DelegatedInkPointRendererGpu { + public: + DelegatedInkPointRendererGpu() = default; + + bool Initialize( + const Microsoft::WRL::ComPtr& dcomp_device2, + const Microsoft::WRL::ComPtr& root_swap_chain) { + if (dcomp_device_ == dcomp_device2.Get() && + swap_chain_ == root_swap_chain.Get() && HasBeenInitialized()) { + return true; + } + + dcomp_device_ = dcomp_device2.Get(); + swap_chain_ = root_swap_chain.Get(); + + Microsoft::WRL::ComPtr ink_trail_device; + TraceEventOnFailure(dcomp_device2.As(&ink_trail_device), + "DelegatedInkPointRendererGpu::Initialize - " + "DCompDevice2 as InkTrailDevice failed"); + if (!ink_trail_device) + return false; + + TraceEventOnFailure( + ink_trail_device->CreateDelegatedInkTrailForSwapChain( + root_swap_chain.Get(), &delegated_ink_trail_), + "DelegatedInkPointRendererGpu::Initialize - Failed to create " + "delegated ink trail."); + if (!delegated_ink_trail_) + return false; + + Microsoft::WRL::ComPtr dcomp_device; + TraceEventOnFailure(dcomp_device2.As(&dcomp_device), + "DelegatedInkPointRendererGpu::Initialize - " + "DCompDevice2 as DCompDevice failed"); + if (!dcomp_device) + return false; + + TraceEventOnFailure(dcomp_device->CreateVisual(&ink_visual_), + "DelegatedInkPointRendererGpu::Initialize - " + "Failed to create ink visual."); + if (!ink_visual_) + return false; + + if (TraceEventOnFailure( + ink_visual_->SetContent(delegated_ink_trail_.Get()), + "DelegatedInkPointRendererGpu::Initialize - SetContent failed")) { + // Initialization has failed because SetContent failed. However, we must + // reset the members so that HasBeenInitialized() does not return true + // when queried. + ink_visual_.Reset(); + delegated_ink_trail_.Reset(); + return false; + } + + return true; + } + + bool HasBeenInitialized() const { + return ink_visual_ && delegated_ink_trail_; + } + + IDCompositionVisual* GetInkVisual() const { return ink_visual_.Get(); } + + bool DelegatedInkIsSupported( + const Microsoft::WRL::ComPtr& dcomp_device) const { + Microsoft::WRL::ComPtr ink_trail_device; + HRESULT hr = dcomp_device.As(&ink_trail_device); + return hr == S_OK; + } + + void SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) { + TRACE_EVENT1("gpu", + "DelegatedInkPointRendererGpu::SetDelegatedInkTrailStartPoint", + "metadata", metadata->ToString()); + metadata_ = std::move(metadata); + // TODO(1052145): Start using OS APIs to inform of the starting point of the + // ink trail. + } + + private: + // Note that this returns true if the HRESULT is anything other than S_OK, + // 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)) + return false; + + TRACE_EVENT_INSTANT1("gpu", name, TRACE_EVENT_SCOPE_THREAD, "hr", hr); + return true; + } + + // 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 ink_visual_; + + // The delegated ink trail object that the ink trail is drawn on. This is the + // content of the ink visual. + Microsoft::WRL::ComPtr 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 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; +}; + +} // namespace gl + +#endif // UI_GL_DELEGATED_INK_POINT_RENDERER_GPU_H_ diff --git a/chromium/ui/gl/direct_composition_surface_win.cc b/chromium/ui/gl/direct_composition_surface_win.cc index cbc5c013068..734e18577b5 100644 --- a/chromium/ui/gl/direct_composition_surface_win.cc +++ b/chromium/ui/gl/direct_composition_surface_win.cc @@ -38,6 +38,8 @@ bool g_overlay_caps_valid = false; // Indicates support for either NV12 or YUY2 overlays. GUARDED_BY // GetOverlayLock(). bool g_supports_overlays = false; +// Whether the GPU can support hardware overlays or not. +bool g_supports_hardware_overlays = false; // Whether the DecodeSwapChain is disabled or not. bool g_decode_swap_chain_disabled = false; // Whether to force the nv12 overlay support. @@ -56,11 +58,21 @@ bool SupportsOverlays() { return g_supports_overlays; } +bool SupportsHardwareOverlays() { + base::AutoLock auto_lock(GetOverlayLock()); + return g_supports_hardware_overlays; +} + void SetSupportsOverlays(bool support) { base::AutoLock auto_lock(GetOverlayLock()); g_supports_overlays = support; } +void SetSupportsHardwareOverlays(bool support) { + base::AutoLock auto_lock(GetOverlayLock()); + g_supports_hardware_overlays = support; +} + bool SupportsSoftwareOverlays() { return base::FeatureList::IsEnabled( features::kDirectCompositionSoftwareOverlays) && @@ -118,6 +130,18 @@ UINT g_rgb10a2_overlay_support_flags = 0; // as supported as well. bool g_enable_bgra8_overlays_with_yuv_overlay_support = false; +// Force enabling DXGI_FORMAT_R10G10B10A2_UNORM format for overlay. Intel +// celake and Tigerlake fail to report the cap of this HDR overlay format. +// TODO(magchen@): Remove this workaround when this cap is fixed in the Intel +// drivers. +bool g_force_rgb10a2_overlay_support = false; + +// Per Intel's request, only use NV12 for overlay when +// COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 is also supported. At least one Intel +// Gen9 SKU does not support NV12 overlays and it cannot be screened by the +// device id. +bool g_check_ycbcr_studio_g22_left_p709_for_nv12_support = false; + void SetOverlaySupportFlagsForFormats(UINT nv12_flags, UINT yuy2_flags, UINT bgra8_flags, @@ -135,6 +159,7 @@ bool FlagsSupportsOverlays(UINT flags) { } void GetGpuDriverOverlayInfo(bool* supports_overlays, + bool* supports_hardware_overlays, DXGI_FORMAT* overlay_format_used, DXGI_FORMAT* overlay_format_used_hdr, UINT* nv12_overlay_support_flags, @@ -143,6 +168,7 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays, UINT* rgb10a2_overlay_support_flags) { // Initialization *supports_overlays = false; + *supports_hardware_overlays = false; *overlay_format_used = DXGI_FORMAT_NV12; *overlay_format_used_hdr = DXGI_FORMAT_R10G10B10A2_UNORM; *nv12_overlay_support_flags = 0; @@ -208,12 +234,11 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays, rgb10a2_overlay_support_flags); if (FlagsSupportsOverlays(*nv12_overlay_support_flags)) { // NV12 format is preferred if it's supported. + *overlay_format_used = DXGI_FORMAT_NV12; + *supports_hardware_overlays = true; - // Per Intel's request, use NV12 only when - // COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 is also supported. Rec 709 is - // commonly used for H.264 and HEVC. At least one Intel Gen9 SKU will not - // support NV12 overlays. - if (CheckOverlayColorSpaceSupport( + if (g_check_ycbcr_studio_g22_left_p709_for_nv12_support && + !CheckOverlayColorSpaceSupport( DXGI_FORMAT_NV12, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, output, d3d11_device)) { // Some new Intel drivers only claim to support unscaled overlays, but @@ -221,15 +246,14 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays, // performing an extra scaling Blt before calling the driver. Even when // scaled overlays aren't actually supported, presentation using the // overlay path should be relatively efficient. - *overlay_format_used = DXGI_FORMAT_NV12; - *supports_overlays = true; + *supports_hardware_overlays = false; } } - if (!*supports_overlays && + if (!*supports_hardware_overlays && FlagsSupportsOverlays(*yuy2_overlay_support_flags)) { // If NV12 isn't supported, fallback to YUY2 if it's supported. *overlay_format_used = DXGI_FORMAT_YUY2; - *supports_overlays = true; + *supports_hardware_overlays = true; } if (g_enable_bgra8_overlays_with_yuv_overlay_support) { if (FlagsSupportsOverlays(*nv12_overlay_support_flags)) @@ -247,6 +271,9 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays, DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, output, d3d11_device)) *rgb10a2_overlay_support_flags = 0; } + if (g_force_rgb10a2_overlay_support) { + *rgb10a2_overlay_support_flags = DXGI_OVERLAY_SUPPORT_FLAG_SCALING; + } // Early out after the first output that reports overlay support. All // outputs are expected to report the same overlay support according to @@ -254,14 +281,12 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays, // https://docs.microsoft.com/en-us/windows-hardware/drivers/display/multiplane-overlay-hardware-requirements // TODO(sunnyps): If the above is true, then we can only look at first // output instead of iterating over all outputs. - if (*supports_overlays) + if (*supports_hardware_overlays) break; } - base::UmaHistogramBoolean("GPU.DirectComposition.HardwareOverlaysSupported", - *supports_overlays); - - if (*supports_overlays || !SupportsSoftwareOverlays()) { + *supports_overlays = *supports_hardware_overlays; + if (*supports_hardware_overlays || !SupportsSoftwareOverlays()) { return; } @@ -283,6 +308,7 @@ void UpdateOverlaySupport() { SetOverlayCapsValid(true); bool supports_overlays = false; + bool supports_hardware_overlays = false; DXGI_FORMAT overlay_format_used = DXGI_FORMAT_NV12; DXGI_FORMAT overlay_format_used_hdr = DXGI_FORMAT_R10G10B10A2_UNORM; UINT nv12_overlay_support_flags = 0; @@ -291,9 +317,10 @@ void UpdateOverlaySupport() { UINT rgb10a2_overlay_support_flags = 0; GetGpuDriverOverlayInfo( - &supports_overlays, &overlay_format_used, &overlay_format_used_hdr, - &nv12_overlay_support_flags, &yuy2_overlay_support_flags, - &bgra8_overlay_support_flags, &rgb10a2_overlay_support_flags); + &supports_overlays, &supports_hardware_overlays, &overlay_format_used, + &overlay_format_used_hdr, &nv12_overlay_support_flags, + &yuy2_overlay_support_flags, &bgra8_overlay_support_flags, + &rgb10a2_overlay_support_flags); if (g_force_nv12_overlay_support) { supports_overlays = true; @@ -318,19 +345,19 @@ void UpdateOverlaySupport() { } } - if (supports_overlays != SupportsOverlays() || - overlay_format_used != g_overlay_format_used) { - // Record the new histograms - if (supports_overlays) { - base::UmaHistogramSparse("GPU.DirectComposition.OverlayFormatUsed3", - overlay_format_used); - } - UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.OverlaysSupported", - supports_overlays); + // Record histograms. + if (supports_overlays) { + base::UmaHistogramSparse("GPU.DirectComposition.OverlayFormatUsed3", + overlay_format_used); } + base::UmaHistogramBoolean("GPU.DirectComposition.OverlaysSupported", + supports_overlays); + base::UmaHistogramBoolean("GPU.DirectComposition.HardwareOverlaysSupported", + supports_hardware_overlays); - // Update global caps + // Update global caps. SetSupportsOverlays(supports_overlays); + SetSupportsHardwareOverlays(supports_hardware_overlays); SetOverlaySupportFlagsForFormats( nv12_overlay_support_flags, yuy2_overlay_support_flags, bgra8_overlay_support_flags, rgb10a2_overlay_support_flags); @@ -451,6 +478,11 @@ bool DirectCompositionSurfaceWin::AreOverlaysSupported() { return SupportsOverlays(); } +bool DirectCompositionSurfaceWin::AreHardwareOverlaysSupported() { + UpdateOverlaySupport(); + return SupportsHardwareOverlays(); +} + // static bool DirectCompositionSurfaceWin::IsDecodeSwapChainSupported() { if (!g_decode_swap_chain_disabled) { @@ -549,6 +581,7 @@ void DirectCompositionSurfaceWin::SetScaledOverlaysSupportedForTesting( g_yuy2_overlay_support_flags &= ~DXGI_OVERLAY_SUPPORT_FLAG_SCALING; g_rgb10a2_overlay_support_flags &= ~DXGI_OVERLAY_SUPPORT_FLAG_SCALING; } + SetSupportsHardwareOverlays(supported); DCHECK_EQ(supported, AreScaledOverlaysSupported()); } @@ -688,6 +721,20 @@ void DirectCompositionSurfaceWin::ForceNV12OverlaySupport() { g_force_nv12_overlay_support = true; } +// static +void DirectCompositionSurfaceWin::ForceRgb10a2OverlaySupport() { + // This has to be set before initializing overlay caps. + DCHECK(!OverlayCapsValid()); + g_force_rgb10a2_overlay_support = true; +} +// static +void DirectCompositionSurfaceWin:: + SetCheckYCbCrStudioG22LeftP709ForNv12Support() { + // This has to be set before initializing overlay caps. + DCHECK(!OverlayCapsValid()); + g_check_ycbcr_studio_g22_left_p709_for_nv12_support = true; +} + bool DirectCompositionSurfaceWin::Initialize(GLSurfaceFormat format) { d3d11_device_ = QueryD3D11DeviceObjectFromANGLE(); if (!d3d11_device_) { @@ -856,6 +903,7 @@ void DirectCompositionSurfaceWin::OnDisplayAdded() { InvalidateOverlayCaps(); UpdateOverlaySupport(); UpdateMonitorInfo(); + layer_tree_->GetHDRMetadataHelper()->UpdateDisplayMetadata(d3d11_device_); RunOverlayHdrGpuInfoUpdateCallback(); } @@ -863,6 +911,7 @@ void DirectCompositionSurfaceWin::OnDisplayRemoved() { InvalidateOverlayCaps(); UpdateOverlaySupport(); UpdateMonitorInfo(); + layer_tree_->GetHDRMetadataHelper()->UpdateDisplayMetadata(d3d11_device_); RunOverlayHdrGpuInfoUpdateCallback(); } @@ -874,6 +923,11 @@ bool DirectCompositionSurfaceWin::SupportsDelegatedInk() { return layer_tree_->SupportsDelegatedInk(); } +void DirectCompositionSurfaceWin::SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) { + layer_tree_->SetDelegatedInkTrailStartPoint(std::move(metadata)); +} + scoped_refptr 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 03da756a3f4..1fe92ebf7aa 100644 --- a/chromium/ui/gl/direct_composition_surface_win.h +++ b/chromium/ui/gl/direct_composition_surface_win.h @@ -19,6 +19,10 @@ #include "ui/gl/gpu_switching_observer.h" #include "ui/gl/vsync_observer.h" +namespace gfx { +class DelegatedInkMetadata; +} // namespace gfx + namespace gl { class DCLayerTree; class DirectCompositionChildSurfaceWin; @@ -54,6 +58,10 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL, // --disable-direct-composition-video-overlays. This function is thread safe. static bool AreOverlaysSupported(); + // Returns if the GPU supports hardware overlays. This function is thread + // safe. + static bool AreHardwareOverlaysSupported(); + // Returns true if zero copy decode swap chain is supported. static bool IsDecodeSwapChainSupported(); static void DisableDecodeSwapChain(); @@ -110,6 +118,14 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL, // IDXGIOutput3::CheckOverlaySupport(). static void ForceNV12OverlaySupport(); + // Forces to enable RGBA101010A2 overlay support regardless of the query + // results from IDXGIOutput3::CheckOverlaySupport(). + static void ForceRgb10a2OverlaySupport(); + + // Enable NV12 overlay support only when + // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 is supported. + static void SetCheckYCbCrStudioG22LeftP709ForNv12Support(); + // GLSurfaceEGL implementation. bool Initialize(GLSurfaceFormat format) override; void Destroy() override; @@ -153,6 +169,8 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL, void OnDisplayMetricsChanged() override; bool SupportsDelegatedInk() override; + void SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) override; HWND window() const { return window_; } diff --git a/chromium/ui/gl/direct_composition_surface_win_unittest.cc b/chromium/ui/gl/direct_composition_surface_win_unittest.cc index 1f575daeda8..c47020fac91 100644 --- a/chromium/ui/gl/direct_composition_surface_win_unittest.cc +++ b/chromium/ui/gl/direct_composition_surface_win_unittest.cc @@ -12,6 +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/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "base/win/scoped_gdi_object.h" @@ -42,7 +43,7 @@ namespace { class TestPlatformDelegate : public ui::PlatformWindowDelegate { public: // ui::PlatformWindowDelegate implementation. - void OnBoundsChanged(const gfx::Rect& new_bounds) override {} + void OnBoundsChanged(const BoundsChange& change) override {} void OnDamageRect(const gfx::Rect& damaged_region) override {} void DispatchEvent(ui::Event* event) override {} void OnCloseRequest() override {} @@ -117,6 +118,9 @@ class DirectCompositionSurfaceTest : public testing::Test { protected: void SetUp() override { + // These tests are assumed to run on battery. + fake_power_monitor_source_.SetOnBatteryPower(true); + // Without this, the following check always fails. gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true); if (!QueryDirectCompositionDevice(QueryD3D11DeviceObjectFromANGLE())) { @@ -170,6 +174,7 @@ class DirectCompositionSurfaceTest : public testing::Test { HWND parent_window_; scoped_refptr surface_; scoped_refptr context_; + base::test::ScopedPowerMonitorTestSource fake_power_monitor_source_; }; TEST_F(DirectCompositionSurfaceTest, TestMakeCurrent) { diff --git a/chromium/ui/gl/features.gni b/chromium/ui/gl/features.gni index 7fbcd0d8175..9c949825fa4 100644 --- a/chromium/ui/gl/features.gni +++ b/chromium/ui/gl/features.gni @@ -9,7 +9,7 @@ import("//build/util/version.gni") declare_args() { # Should ANGLE be linked statically? - use_static_angle = false + use_static_angle = is_android # Should EGL support be compiled? # Can be overriden to test during bring up of EGL support on other platforms. diff --git a/chromium/ui/gl/gl_context_egl.cc b/chromium/ui/gl/gl_context_egl.cc index a6870ee21c2..c27b3edae4a 100644 --- a/chromium/ui/gl/gl_context_egl.cc +++ b/chromium/ui/gl/gl_context_egl.cc @@ -237,15 +237,17 @@ bool GLContextEGL::Initialize(GLSurface* compatible_surface, } if (GLSurfaceEGL::IsANGLEPowerPreferenceSupported()) { - switch (attribs.gpu_preference) { - case GpuPreference ::kDefault: + GpuPreference pref = attribs.gpu_preference; + pref = GLContext::AdjustGpuPreference(pref); + switch (pref) { + case GpuPreference::kDefault: // Don't request any GPU, let ANGLE and the native driver decide. break; - case GpuPreference ::kLowPower: + case GpuPreference::kLowPower: context_attributes.push_back(EGL_POWER_PREFERENCE_ANGLE); context_attributes.push_back(EGL_LOW_POWER_ANGLE); break; - case GpuPreference ::kHighPerformance: + case GpuPreference::kHighPerformance: context_attributes.push_back(EGL_POWER_PREFERENCE_ANGLE); context_attributes.push_back(EGL_HIGH_POWER_ANGLE); break; diff --git a/chromium/ui/gl/gl_image_d3d_unittest.cc b/chromium/ui/gl/gl_image_d3d_unittest.cc index e76c5598f24..febd42eeb88 100644 --- a/chromium/ui/gl/gl_image_d3d_unittest.cc +++ b/chromium/ui/gl/gl_image_d3d_unittest.cc @@ -25,9 +25,10 @@ class GLImageD3DTestDelegate : public GLImageTestDelegateBase { void WillTearDown() override { d3d11_device_ = nullptr; } - base::Optional GetPreferedGLImplementation() + base::Optional GetPreferedGLImplementation() const override { - return base::Optional(kGLImplementationEGLANGLE); + return base::Optional( + GLImplementationParts(ANGLEImplementation::kD3D11)); } bool SkipTest() const override { return !d3d11_device_; } diff --git a/chromium/ui/gl/gl_image_egl.cc b/chromium/ui/gl/gl_image_egl.cc index 930d35e7bca..60dd406751b 100644 --- a/chromium/ui/gl/gl_image_egl.cc +++ b/chromium/ui/gl/gl_image_egl.cc @@ -4,6 +4,10 @@ #include "ui/gl/gl_image_egl.h" +#include "base/metrics/histogram_macros.h" +#include "base/time/time.h" +#include "base/timer/elapsed_timer.h" +#include "base/timer/timer.h" #include "ui/gl/egl_util.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_enums.h" @@ -52,10 +56,18 @@ bool GLImageEGL::BindTexImage(unsigned target) { DCHECK_EQ(BIND, ShouldBindOrCopy()); glEGLImageTargetTexture2DOES(target, egl_image_); + base::ElapsedTimer thread_blocked_timer; const GLenum error = glGetError(); + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "Gpu.GL.GetErrorDuration.GLImageEGL.BindTexImage", + thread_blocked_timer.Elapsed(), base::TimeDelta::FromMicroseconds(10), + base::TimeDelta::FromMilliseconds(16), 100); DLOG_IF(ERROR, error != GL_NO_ERROR) << "Error binding EGLImage: " << GLEnums::GetStringError(error); + + UMA_HISTOGRAM_BOOLEAN("Gpu.GL.GetErrorResult.GLImageEGL.BindTexImage", + error != GL_NO_ERROR); return error == GL_NO_ERROR; } diff --git a/chromium/ui/gl/gl_image_egl_pixmap.cc b/chromium/ui/gl/gl_image_egl_pixmap.cc index e226c76f570..6c5612de92e 100644 --- a/chromium/ui/gl/gl_image_egl_pixmap.cc +++ b/chromium/ui/gl/gl_image_egl_pixmap.cc @@ -6,9 +6,6 @@ #include -#include "base/logging.h" -#include "build/build_config.h" -#include "ui/base/ui_base_features.h" #include "ui/gl/buffer_format_utils.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_surface_glx.h" @@ -17,13 +14,8 @@ namespace gl { inline EGLDisplay FromXDisplay() { -#if defined(USE_X11) - if (!features::IsUsingOzonePlatform()) { - if (auto* x_display = x11::Connection::Get()->GetXlibDisplay().display()) - return eglGetDisplay(reinterpret_cast(x_display)); - } -#endif - return EGL_NO_DISPLAY; + auto* x_display = x11::Connection::Get()->GetXlibDisplay().display(); + return eglGetDisplay(reinterpret_cast(x_display)); } GLImageEGLPixmap::GLImageEGLPixmap(const gfx::Size& size, diff --git a/chromium/ui/gl/gl_image_native_pixmap_unittest.cc b/chromium/ui/gl/gl_image_native_pixmap_unittest.cc index c7ded389c2d..cc1ec600556 100644 --- a/chromium/ui/gl/gl_image_native_pixmap_unittest.cc +++ b/chromium/ui/gl/gl_image_native_pixmap_unittest.cc @@ -32,12 +32,14 @@ const uint8_t kImageColor[] = {0x30, 0x40, 0x10, 0xFF}; template class GLImageNativePixmapTestDelegate : public GLImageTestDelegateBase { public: - base::Optional GetPreferedGLImplementation() + base::Optional GetPreferedGLImplementation() const override { #if defined(OS_WIN) - return base::Optional(kGLImplementationEGLANGLE); + return base::Optional(GLImplementationParts( + kGLImplementationEGLANGLE, ANGLEImplementation::kNone)); #else - return base::Optional(kGLImplementationEGLGLES2); + return base::Optional( + GLImplementationParts(kGLImplementationEGLGLES2)); #endif } diff --git a/chromium/ui/gl/gl_implementation.cc b/chromium/ui/gl/gl_implementation.cc index 763c1cc11c1..5acbd036bd8 100644 --- a/chromium/ui/gl/gl_implementation.cc +++ b/chromium/ui/gl/gl_implementation.cc @@ -25,27 +25,85 @@ namespace gl { +ANGLEImplementation MakeANGLEImplementation( + const GLImplementation gl_impl, + const ANGLEImplementation angle_impl) { + if (gl_impl == kGLImplementationEGLANGLE) { + if (angle_impl == ANGLEImplementation::kNone) { + return ANGLEImplementation::kDefault; + } else { + return angle_impl; + } + } else { + return ANGLEImplementation::kNone; + } +} + +GLImplementationParts::GLImplementationParts( + const ANGLEImplementation angle_impl) + : gl(kGLImplementationEGLANGLE), + angle(MakeANGLEImplementation(kGLImplementationEGLANGLE, angle_impl)) {} + +GLImplementationParts::GLImplementationParts(const GLImplementation gl_impl) + : gl(gl_impl), + angle(MakeANGLEImplementation(gl_impl, ANGLEImplementation::kNone)) {} + +bool GLImplementationParts::IsValid() const { + if (angle == ANGLEImplementation::kNone) { + return (gl != kGLImplementationEGLANGLE); + } else { + return (gl == kGLImplementationEGLANGLE); + } +} + namespace { const struct { - const char* name; - GLImplementation implementation; + const char* gl_name; + const char* angle_name; + GLImplementationParts implementation; } kGLImplementationNamePairs[] = { - {kGLImplementationDesktopName, kGLImplementationDesktopGL}, - {kGLImplementationSwiftShaderName, kGLImplementationSwiftShaderGL}, + {kGLImplementationDesktopName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationDesktopGL)}, + {kGLImplementationSwiftShaderName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationSwiftShaderGL)}, #if defined(OS_APPLE) - {kGLImplementationAppleName, kGLImplementationAppleGL}, + {kGLImplementationAppleName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationAppleGL)}, #endif - {kGLImplementationEGLName, kGLImplementationEGLGLES2}, - {kGLImplementationANGLEName, kGLImplementationEGLANGLE}, - {kGLImplementationMockName, kGLImplementationMockGL}, - {kGLImplementationStubName, kGLImplementationStubGL}, - {kGLImplementationDisabledName, kGLImplementationDisabled}}; + {kGLImplementationEGLName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationEGLGLES2)}, + {kGLImplementationANGLEName, kANGLEImplementationNoneName, + GLImplementationParts(ANGLEImplementation::kDefault)}, + {kGLImplementationANGLEName, kANGLEImplementationD3D9Name, + GLImplementationParts(ANGLEImplementation::kD3D9)}, + {kGLImplementationANGLEName, kANGLEImplementationD3D11Name, + GLImplementationParts(ANGLEImplementation::kD3D11)}, + {kGLImplementationANGLEName, kANGLEImplementationOpenGLName, + GLImplementationParts(ANGLEImplementation::kOpenGL)}, + {kGLImplementationANGLEName, kANGLEImplementationOpenGLESName, + GLImplementationParts(ANGLEImplementation::kOpenGLES)}, + {kGLImplementationANGLEName, kANGLEImplementationVulkanName, + GLImplementationParts(ANGLEImplementation::kVulkan)}, + {kGLImplementationANGLEName, kANGLEImplementationMetalName, + GLImplementationParts(ANGLEImplementation::kMetal)}, + {kGLImplementationANGLEName, kANGLEImplementationDefaultName, + GLImplementationParts(ANGLEImplementation::kDefault)}, + {kGLImplementationANGLEName, kANGLEImplementationSwiftShaderName, + GLImplementationParts(ANGLEImplementation::kSwiftShader)}, + {kGLImplementationANGLEName, kANGLEImplementationNullName, + GLImplementationParts(ANGLEImplementation::kNull)}, + {kGLImplementationMockName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationMockGL)}, + {kGLImplementationStubName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationStubGL)}, + {kGLImplementationDisabledName, kANGLEImplementationNoneName, + GLImplementationParts(kGLImplementationDisabled)}}; typedef std::vector LibraryArray; -GLImplementation g_gl_implementation = kGLImplementationNone; -ANGLEImplementation g_angle_implementation = ANGLEImplementation::kNone; +GLImplementationParts g_gl_implementation = + GLImplementationParts(kGLImplementationNone); LibraryArray* g_libraries; GLGetProcAddressProc g_get_proc_address; @@ -105,48 +163,99 @@ EGLApi* g_current_egl_context; GLXApi* g_current_glx_context; #endif -GLImplementation GetNamedGLImplementation(const std::string& name) { - for (size_t i = 0; i < base::size(kGLImplementationNamePairs); ++i) { - if (name == kGLImplementationNamePairs[i].name) - return kGLImplementationNamePairs[i].implementation; +GLImplementationParts GetNamedGLImplementation(const std::string& gl_name, + const std::string& angle_name) { + for (auto name_pair : kGLImplementationNamePairs) { + if (gl_name == name_pair.gl_name && angle_name == name_pair.angle_name) + return name_pair.implementation; } - return kGLImplementationNone; + return GLImplementationParts(kGLImplementationNone); +} + +GLImplementationParts GetLegacySoftwareGLImplementation() { + return GLImplementationParts(kGLImplementationSwiftShaderGL); +} + +GLImplementationParts GetSoftwareGLImplementation() { + return GLImplementationParts(ANGLEImplementation::kSwiftShader); +} + +GLImplementationParts GetSoftwareGLForTestsImplementation() { + return GetLegacySoftwareGLImplementation(); +} + +bool IsSoftwareGLImplementation(GLImplementationParts implementation) { + return (implementation == GetLegacySoftwareGLImplementation()) || + (implementation == GetSoftwareGLImplementation()); } -GLImplementation GetSoftwareGLImplementation() { - return kGLImplementationSwiftShaderGL; +void SetSoftwareGLCommandLineSwitches(base::CommandLine* command_line, + bool legacy_software_gl) { + if (legacy_software_gl) { + command_line->AppendSwitchASCII( + switches::kUseGL, + gl::GetGLImplementationGLName(gl::GetLegacySoftwareGLImplementation())); + } else { + GLImplementationParts implementation = GetSoftwareGLImplementation(); + command_line->AppendSwitchASCII( + switches::kUseGL, gl::GetGLImplementationGLName(implementation)); + command_line->AppendSwitchASCII( + switches::kUseANGLE, gl::GetGLImplementationANGLEName(implementation)); + } } -const char* GetGLImplementationName(GLImplementation implementation) { - for (size_t i = 0; i < base::size(kGLImplementationNamePairs); ++i) { - if (implementation == kGLImplementationNamePairs[i].implementation) - return kGLImplementationNamePairs[i].name; +const char* GetGLImplementationGLName(GLImplementationParts implementation) { + for (auto name_pair : kGLImplementationNamePairs) { + if (implementation.gl == name_pair.implementation.gl && + implementation.angle == name_pair.implementation.angle) + return name_pair.gl_name; } return "unknown"; } +const char* GetGLImplementationANGLEName(GLImplementationParts implementation) { + for (auto name_pair : kGLImplementationNamePairs) { + if (implementation.gl == name_pair.implementation.gl && + implementation.angle == name_pair.implementation.angle) + return name_pair.angle_name; + } + + return ""; +} + +void SetGLImplementationParts(const GLImplementationParts& implementation) { + DCHECK(implementation.IsValid()); + g_gl_implementation = GLImplementationParts(implementation); +} + +const GLImplementationParts& GetGLImplementationParts() { + return g_gl_implementation; +} + void SetGLImplementation(GLImplementation implementation) { - g_gl_implementation = implementation; + g_gl_implementation = GLImplementationParts(implementation); + DCHECK(g_gl_implementation.IsValid()); } GLImplementation GetGLImplementation() { - return g_gl_implementation; + return g_gl_implementation.gl; } void SetANGLEImplementation(ANGLEImplementation implementation) { - g_angle_implementation = implementation; + g_gl_implementation = GLImplementationParts(implementation); + DCHECK(g_gl_implementation.IsValid()); } ANGLEImplementation GetANGLEImplementation() { - return g_angle_implementation; + return g_gl_implementation.angle; } bool HasDesktopGLFeatures() { - return kGLImplementationDesktopGL == g_gl_implementation || - kGLImplementationDesktopGLCoreProfile == g_gl_implementation || - kGLImplementationAppleGL == g_gl_implementation; + return kGLImplementationDesktopGL == g_gl_implementation.gl || + kGLImplementationDesktopGLCoreProfile == g_gl_implementation.gl || + kGLImplementationAppleGL == g_gl_implementation.gl; } void AddGLNativeLibrary(base::NativeLibrary library) { @@ -171,7 +280,7 @@ void SetGLGetProcAddressProc(GLGetProcAddressProc proc) { NO_SANITIZE("cfi-icall") GLFunctionPointerType GetGLProcAddress(const char* name) { - DCHECK(g_gl_implementation != kGLImplementationNone); + DCHECK(g_gl_implementation.gl != kGLImplementationNone); if (g_libraries) { for (size_t i = 0; i < g_libraries->size(); ++i) { diff --git a/chromium/ui/gl/gl_implementation.h b/chromium/ui/gl/gl_implementation.h index c6cefe206be..2c34023a859 100644 --- a/chromium/ui/gl/gl_implementation.h +++ b/chromium/ui/gl/gl_implementation.h @@ -17,6 +17,10 @@ #include "ui/gl/gl_export.h" #include "ui/gl/gl_switches.h" +namespace base { +class CommandLine; +} + namespace gl { class GLApi; @@ -49,7 +53,22 @@ enum class ANGLEImplementation { kVulkan = 6, kSwiftShader = 7, kMetal = 8, - kMaxValue = kMetal, + kDefault = 9, + kMaxValue = kDefault, +}; + +struct GL_EXPORT GLImplementationParts { + explicit GLImplementationParts(const ANGLEImplementation angle_impl); + explicit GLImplementationParts(const GLImplementation gl_impl); + + GLImplementation gl = kGLImplementationNone; + ANGLEImplementation angle = ANGLEImplementation::kNone; + + constexpr bool operator==(const GLImplementationParts& other) const { + return (gl == other.gl && angle == other.angle); + } + + bool IsValid() const; }; struct GL_EXPORT GLWindowSystemBindingInfo { @@ -93,6 +112,13 @@ class GL_EXPORT DisableNullDrawGLBindings { bool initial_enabled_; }; +// Set the current GL and ANGLE implementation. +GL_EXPORT void SetGLImplementationParts( + const GLImplementationParts& implementation); + +// Get the current GL and ANGLE implementation. +GL_EXPORT const GLImplementationParts& GetGLImplementationParts(); + // Set the current GL implementation. GL_EXPORT void SetGLImplementation(GLImplementation implementation); @@ -105,18 +131,32 @@ GL_EXPORT void SetANGLEImplementation(ANGLEImplementation implementation); // Get the current ANGLE implementation. GL_EXPORT ANGLEImplementation GetANGLEImplementation(); -// Get the software GL implementation for the current platform. -GL_EXPORT GLImplementation GetSoftwareGLImplementation(); +// Get the software GL implementation +GL_EXPORT GLImplementationParts GetLegacySoftwareGLImplementation(); +GL_EXPORT GLImplementationParts GetSoftwareGLImplementation(); +GL_EXPORT GLImplementationParts GetSoftwareGLForTestsImplementation(); + +// Set the software GL implementation on the provided command line +GL_EXPORT void SetSoftwareGLCommandLineSwitches(base::CommandLine* command_line, + bool legacy_software_gl); + +// Whether the implementation is one of the software GL implementations +GL_EXPORT bool IsSoftwareGLImplementation(GLImplementationParts implementation); // Does the underlying GL support all features from Desktop GL 2.0 that were // removed from the ES 2.0 spec without requiring specific extension strings. GL_EXPORT bool HasDesktopGLFeatures(); // Get the GL implementation with a given name. -GL_EXPORT GLImplementation GetNamedGLImplementation(const std::string& name); +GL_EXPORT GLImplementationParts +GetNamedGLImplementation(const std::string& gl_name, + const std::string& angle_name); // Get the name of a GL implementation. -GL_EXPORT const char* GetGLImplementationName(GLImplementation implementation); +GL_EXPORT const char* GetGLImplementationGLName( + GLImplementationParts implementation); +GL_EXPORT const char* GetGLImplementationANGLEName( + GLImplementationParts implementation); // Add a native library to those searched for GL entry points. GL_EXPORT void AddGLNativeLibrary(base::NativeLibrary library); diff --git a/chromium/ui/gl/gl_surface.cc b/chromium/ui/gl/gl_surface.cc index 9d304c947d5..c180260e045 100644 --- a/chromium/ui/gl/gl_surface.cc +++ b/chromium/ui/gl/gl_surface.cc @@ -4,6 +4,8 @@ #include "ui/gl/gl_surface.h" +#include + #include "base/check.h" #include "base/command_line.h" #include "base/lazy_instance.h" @@ -181,6 +183,10 @@ bool GLSurface::IsSurfaceless() const { return false; } +bool GLSurface::SupportsViewporter() const { + return false; +} + gfx::SurfaceOrigin GLSurface::GetOrigin() const { return gfx::SurfaceOrigin::kBottomLeft; } @@ -457,6 +463,10 @@ bool GLSurfaceAdapter::IsSurfaceless() const { return surface_->IsSurfaceless(); } +bool GLSurfaceAdapter::SupportsViewporter() const { + return surface_->SupportsViewporter(); +} + gfx::SurfaceOrigin GLSurfaceAdapter::GetOrigin() const { return surface_->GetOrigin(); } @@ -537,7 +547,12 @@ bool GLSurfaceAdapter::SupportsDelegatedInk() { return surface_->SupportsDelegatedInk(); } -GLSurfaceAdapter::~GLSurfaceAdapter() {} +void GLSurfaceAdapter::SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) { + surface_->SetDelegatedInkTrailStartPoint(std::move(metadata)); +} + +GLSurfaceAdapter::~GLSurfaceAdapter() = default; scoped_refptr InitializeGLSurfaceWithFormat( scoped_refptr surface, GLSurfaceFormat format) { diff --git a/chromium/ui/gl/gl_surface.h b/chromium/ui/gl/gl_surface.h index 6fc339049f5..6aa6a8dded5 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 "ui/gfx/delegated_ink_metadata.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" @@ -261,6 +262,10 @@ class GL_EXPORT GLSurface : public base::RefCounted, virtual bool IsSurfaceless() const; + // Returns true if this surface permits scheduling an isothetic sub-rectangle + // (i.e. viewport) of its contents for display. + virtual bool SupportsViewporter() const; + virtual gfx::SurfaceOrigin GetOrigin() const; // Returns true if SwapBuffers or PostSubBuffers causes a flip, such that @@ -318,6 +323,8 @@ class GL_EXPORT GLSurface : public base::RefCounted, static bool ExtensionsContain(const char* extensions, const char* name); virtual bool SupportsDelegatedInk(); + virtual void SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) {} protected: virtual ~GLSurface(); @@ -393,6 +400,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface { bool ScheduleDCLayer(const ui::DCRendererLayerParams& params) override; bool SetEnableDCLayers(bool enable) override; bool IsSurfaceless() const override; + bool SupportsViewporter() const override; gfx::SurfaceOrigin GetOrigin() const override; bool BuffersFlipped() const override; bool SupportsDCLayers() const override; @@ -414,6 +422,8 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface { bool IsCurrent() override; bool SupportsDelegatedInk() override; + void SetDelegatedInkTrailStartPoint( + std::unique_ptr metadata) 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 d6ca1917f0d..cce04278d5e 100644 --- a/chromium/ui/gl/gl_surface_egl.cc +++ b/chromium/ui/gl/gl_surface_egl.cc @@ -184,6 +184,8 @@ class EGLGpuSwitchingObserver; EGLDisplay g_egl_display = EGL_NO_DISPLAY; EGLDisplayPlatform g_native_display(EGL_DEFAULT_DISPLAY); +DisplayType g_display_type = DisplayType::DEFAULT; + const char* g_egl_client_extensions = nullptr; const char* g_egl_extensions = nullptr; bool g_egl_create_context_robustness_supported = false; @@ -556,7 +558,7 @@ const char* DisplayTypeString(DisplayType display_type) { case ANGLE_D3D11on12: return "D3D11on12"; case ANGLE_SWIFTSHADER: - return "SwiftShader"; + return "SwANGLE"; case ANGLE_OPENGL_EGL: return "OpenGLEGL"; case ANGLE_OPENGLES_EGL: @@ -792,19 +794,31 @@ void GetEGLInitDisplays(bool supports_angle_d3d, bool supports_angle_metal, const base::CommandLine* command_line, std::vector* init_displays) { + bool usingSoftwareGLForTests = + command_line->HasSwitch(switches::kOverrideUseSoftwareGLForTests); + bool isSwANGLE = GetGLImplementationParts() == GetSoftwareGLImplementation(); + // SwiftShader does not use the platform extensions + // Note: Do not use SwiftShader if we've explicitly selected SwANGLE if (command_line->GetSwitchValueASCII(switches::kUseGL) == - kGLImplementationSwiftShaderForWebGLName) { + kGLImplementationSwiftShaderForWebGLName && + !(usingSoftwareGLForTests && isSwANGLE)) { AddInitDisplay(init_displays, SWIFT_SHADER); return; } + // If we're already requesting software GL, make sure we don't fallback to the + // GPU + bool forceSoftwareGL = IsSoftwareGLImplementation(GetGLImplementationParts()); + std::string requested_renderer = - command_line->GetSwitchValueASCII(switches::kUseANGLE); + forceSoftwareGL ? kANGLEImplementationSwiftShaderName + : command_line->GetSwitchValueASCII(switches::kUseANGLE); bool use_angle_default = - !command_line->HasSwitch(switches::kUseANGLE) || - requested_renderer == kANGLEImplementationDefaultName; + !forceSoftwareGL && + (!command_line->HasSwitch(switches::kUseANGLE) || + requested_renderer == kANGLEImplementationDefaultName); if (supports_angle_null && requested_renderer == kANGLEImplementationNullName) { @@ -1013,16 +1027,26 @@ bool GLSurfaceEGL::InitializeOneOffCommon() { g_egl_robust_resource_init_supported = HasEGLExtension("EGL_ANGLE_robust_resource_initialization"); + // Check if SurfacelessEGL is supported. + g_egl_surfaceless_context_supported = + HasEGLExtension("EGL_KHR_surfaceless_context"); + // TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary // workaround, since code written for Android WebView takes different paths // based on whether GL surface objects have underlying EGL surface handles, - // conflicting with the use of surfaceless. See https://crbug.com/382349 + // conflicting with the use of surfaceless. ANGLE can still expose surfacelss + // because it is emulated with pbuffers if native support is not present. See + // https://crbug.com/382349. + #if defined(OS_ANDROID) - DCHECK(!g_egl_surfaceless_context_supported); -#else - // Check if SurfacelessEGL is supported. - g_egl_surfaceless_context_supported = - HasEGLExtension("EGL_KHR_surfaceless_context"); + // Use the WebGL compatibility extension for detecting ANGLE. ANGLE always + // exposes it. + bool is_angle = g_egl_create_context_webgl_compatability_supported; + if (!is_angle) { + g_egl_surfaceless_context_supported = false; + } +#endif + if (g_egl_surfaceless_context_supported) { // EGL_KHR_surfaceless_context is supported but ensure // GL_OES_surfaceless_context is also supported. We need a current context @@ -1040,7 +1064,6 @@ bool GLSurfaceEGL::InitializeOneOffCommon() { context->ReleaseCurrent(surface.get()); } } -#endif // The native fence sync extension is a bit complicated. It's reported as // present for ChromeOS, but Android currently doesn't report this extension @@ -1140,6 +1163,11 @@ EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { return g_native_display.GetDisplay(); } +// static +DisplayType GLSurfaceEGL::GetDisplayType() { + return g_display_type; +} + // static const char* GLSurfaceEGL::GetEGLClientExtensions() { return g_egl_client_extensions ? g_egl_client_extensions : ""; @@ -1349,9 +1377,9 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform native_display) { } std::ostringstream display_type_string; - auto gl_implementation = GetGLImplementation(); - display_type_string << GetGLImplementationName(gl_implementation); - if (gl_implementation == kGLImplementationEGLANGLE) { + auto gl_implementation = GetGLImplementationParts(); + display_type_string << GetGLImplementationGLName(gl_implementation); + if (gl_implementation.gl == kGLImplementationEGLANGLE) { display_type_string << ":" << DisplayTypeString(display_type); } @@ -1363,6 +1391,7 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay(EGLDisplayPlatform native_display) { UMA_HISTOGRAM_ENUMERATION("GPU.EGLDisplayType", display_type, DISPLAY_TYPE_MAX); g_egl_display = display; + g_display_type = display_type; break; } diff --git a/chromium/ui/gl/gl_surface_egl.h b/chromium/ui/gl/gl_surface_egl.h index 33f36aed459..c649b5fa7b5 100644 --- a/chromium/ui/gl/gl_surface_egl.h +++ b/chromium/ui/gl/gl_surface_egl.h @@ -104,6 +104,7 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface { static EGLDisplay GetHardwareDisplay(); static EGLDisplay InitializeDisplay(EGLDisplayPlatform native_display); static EGLNativeDisplayType GetNativeDisplay(); + static DisplayType GetDisplayType(); // These aren't particularly tied to surfaces, but since we already // have the static InitializeOneOff here, it's easiest to reuse its diff --git a/chromium/ui/gl/gl_surface_egl_unittest.cc b/chromium/ui/gl/gl_surface_egl_unittest.cc index 9f75776dd5d..8212f7dece6 100644 --- a/chromium/ui/gl/gl_surface_egl_unittest.cc +++ b/chromium/ui/gl/gl_surface_egl_unittest.cc @@ -33,10 +33,10 @@ class GLSurfaceEGLTest : public testing::Test { void SetUp() override { #if defined(OS_WIN) GLSurfaceTestSupport::InitializeOneOffImplementation( - GLImplementation::kGLImplementationEGLANGLE, true); + GLImplementationParts(kGLImplementationEGLANGLE), true); #else GLSurfaceTestSupport::InitializeOneOffImplementation( - GLImplementation::kGLImplementationEGLGLES2, true); + GLImplementationParts(kGLImplementationEGLGLES2), true); #endif } @@ -72,7 +72,7 @@ TEST_F(GLSurfaceEGLTest, MAYBE_SurfaceFormatTest) { class TestPlatformDelegate : public ui::PlatformWindowDelegate { public: // ui::PlatformWindowDelegate implementation. - void OnBoundsChanged(const gfx::Rect& new_bounds) override {} + void OnBoundsChanged(const BoundsChange& change) override {} void OnDamageRect(const gfx::Rect& damaged_region) override {} void DispatchEvent(ui::Event* event) override {} void OnCloseRequest() override {} diff --git a/chromium/ui/gl/gl_surface_egl_x11.cc b/chromium/ui/gl/gl_surface_egl_x11.cc index 980227258b2..8b48842f495 100644 --- a/chromium/ui/gl/gl_surface_egl_x11.cc +++ b/chromium/ui/gl/gl_surface_egl_x11.cc @@ -5,48 +5,14 @@ #include "ui/gl/gl_surface_egl_x11.h" #include "base/stl_util.h" -#include "base/threading/thread_task_runner_handle.h" -#include "ui/base/x/x11_display_util.h" #include "ui/base/x/x11_util.h" -#include "ui/gfx/x/randr.h" +#include "ui/base/x/x11_xrandr_interval_only_vsync_provider.h" #include "ui/gfx/x/xproto.h" #include "ui/gfx/x/xproto_util.h" #include "ui/gl/egl_util.h" namespace gl { -namespace { - -class XrandrIntervalOnlyVSyncProvider : public gfx::VSyncProvider { - public: - explicit XrandrIntervalOnlyVSyncProvider() - : interval_(base::TimeDelta::FromSeconds(1 / 60.)) {} - - void GetVSyncParameters(UpdateVSyncCallback callback) override { - if (++calls_since_last_update_ >= kCallsBetweenUpdates) { - calls_since_last_update_ = 0; - interval_ = ui::GetPrimaryDisplayRefreshIntervalFromXrandr(); - } - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), base::TimeTicks(), interval_)); - } - - bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase, - base::TimeDelta* interval) override { - return false; - } - bool SupportGetVSyncParametersIfAvailable() const override { return false; } - bool IsHWClock() const override { return false; } - - private: - base::TimeDelta interval_; - static const int kCallsBetweenUpdates = 100; - int calls_since_last_update_ = kCallsBetweenUpdates; -}; - -} // namespace - NativeViewGLSurfaceEGLX11::NativeViewGLSurfaceEGLX11(x11::Window window) : NativeViewGLSurfaceEGL(static_cast(window), nullptr) {} @@ -55,9 +21,6 @@ bool NativeViewGLSurfaceEGLX11::Initialize(GLSurfaceFormat format) { return false; auto* connection = x11::Connection::Get(); - // Synchronize the Xlib display to ensure ANGLE's CreateWindow request - // completes before we make our QueryTree request below. - connection->GetXlibDisplay(x11::XlibDisplayType::kSyncing); // Query all child windows and store them. ANGLE creates a child window when // eglCreateWindowSurface is called on X11 and expose events from this window // need to be received by this class. Since ANGLE is using a separate @@ -113,7 +76,7 @@ x11::Connection* NativeViewGLSurfaceEGLX11::GetXNativeConnection() const { std::unique_ptr NativeViewGLSurfaceEGLX11::CreateVsyncProviderInternal() { - return std::make_unique(); + return std::make_unique(); } void NativeViewGLSurfaceEGLX11::OnEvent(const x11::Event& x11_event) { diff --git a/chromium/ui/gl/gl_surface_glx.cc b/chromium/ui/gl/gl_surface_glx.cc index 6ceefd62e6a..6a8e2536b81 100644 --- a/chromium/ui/gl/gl_surface_glx.cc +++ b/chromium/ui/gl/gl_surface_glx.cc @@ -24,6 +24,7 @@ #include "build/build_config.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" #include "ui/events/platform/platform_event_source.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/x/xproto_util.h" @@ -667,18 +668,9 @@ bool NativeViewGLSurfaceGLX::Initialize(GLSurfaceFormat format) { presentation_helper_ = std::make_unique(vsync_provider_.get()); } else { - // Assume a refresh rate of 59.9 Hz, which will cause us to skip - // 1 frame every 10 seconds on a 60Hz monitor, but will prevent us - // from blocking the GPU service due to back pressure. This would still - // encounter backpressure on a <60Hz monitor, but hopefully that is - // not common. - const base::TimeTicks kDefaultTimebase; - const base::TimeDelta kDefaultInterval = - base::TimeDelta::FromSeconds(1) / 59.9; - vsync_provider_ = std::make_unique( - kDefaultTimebase, kDefaultInterval); + vsync_provider_ = std::make_unique(); presentation_helper_ = std::make_unique( - kDefaultTimebase, kDefaultInterval); + base::TimeTicks(), ui::GetPrimaryDisplayRefreshIntervalFromXrandr()); } return true; diff --git a/chromium/ui/gl/gl_switches.cc b/chromium/ui/gl/gl_switches.cc index 9a458e8c194..8c94f9f2a7f 100644 --- a/chromium/ui/gl/gl_switches.cc +++ b/chromium/ui/gl/gl_switches.cc @@ -35,6 +35,7 @@ const char kANGLEImplementationNullName[] = "null"; const char kANGLEImplementationVulkanName[] = "vulkan"; const char kANGLEImplementationSwiftShaderName[] = "swiftshader"; const char kANGLEImplementationMetalName[] = "metal"; +const char kANGLEImplementationNoneName[] = ""; // Special switches for "NULL"/stub driver implementations. const char kANGLEImplementationD3D11NULLName[] = "d3d11-null"; diff --git a/chromium/ui/gl/gl_switches.h b/chromium/ui/gl/gl_switches.h index 81ae0db537b..184f9a44dbb 100644 --- a/chromium/ui/gl/gl_switches.h +++ b/chromium/ui/gl/gl_switches.h @@ -35,6 +35,7 @@ GL_EXPORT extern const char kANGLEImplementationNullName[]; GL_EXPORT extern const char kANGLEImplementationVulkanName[]; GL_EXPORT extern const char kANGLEImplementationSwiftShaderName[]; GL_EXPORT extern const char kANGLEImplementationMetalName[]; +GL_EXPORT extern const char kANGLEImplementationNoneName[]; GL_EXPORT extern const char kANGLEImplementationD3D11NULLName[]; GL_EXPORT extern const char kANGLEImplementationOpenGLNULLName[]; diff --git a/chromium/ui/gl/hdr_metadata_helper_win.cc b/chromium/ui/gl/hdr_metadata_helper_win.cc index 7bae9b7af8f..633ed290010 100644 --- a/chromium/ui/gl/hdr_metadata_helper_win.cc +++ b/chromium/ui/gl/hdr_metadata_helper_win.cc @@ -17,7 +17,7 @@ namespace gl { HDRMetadataHelperWin::HDRMetadataHelperWin( const Microsoft::WRL::ComPtr& d3d11_device) { - CacheDisplayMetadata(d3d11_device); + UpdateDisplayMetadata(d3d11_device); } HDRMetadataHelperWin::~HDRMetadataHelperWin() = default; @@ -27,7 +27,7 @@ HDRMetadataHelperWin::GetDisplayMetadata() { return hdr_metadata_; } -void HDRMetadataHelperWin::CacheDisplayMetadata( +void HDRMetadataHelperWin::UpdateDisplayMetadata( const Microsoft::WRL::ComPtr& d3d11_device) { hdr_metadata_.reset(); diff --git a/chromium/ui/gl/hdr_metadata_helper_win.h b/chromium/ui/gl/hdr_metadata_helper_win.h index 4ae73be2e1a..d276f052bf6 100644 --- a/chromium/ui/gl/hdr_metadata_helper_win.h +++ b/chromium/ui/gl/hdr_metadata_helper_win.h @@ -30,16 +30,19 @@ class GL_EXPORT HDRMetadataHelperWin { ~HDRMetadataHelperWin(); // Return the metadata for the display, if available. Must call - // CacheDisplayMetadata first. + // UpdateDisplayMetadata first. base::Optional GetDisplayMetadata(); + // Query the display metadata from all monitors. In the event of monitor + // hot plugging, the metadata should be updated again. + void UpdateDisplayMetadata( + const Microsoft::WRL::ComPtr& d3d11_device); + // Convert |hdr_metadata| to DXGI's metadata format. static DXGI_HDR_METADATA_HDR10 HDRMetadataToDXGI( const gfx::HDRMetadata& hdr_metadata); private: - void CacheDisplayMetadata( - const Microsoft::WRL::ComPtr& d3d11_device); base::Optional hdr_metadata_; diff --git a/chromium/ui/gl/init/create_gr_gl_interface.cc b/chromium/ui/gl/init/create_gr_gl_interface.cc index b45925ea594..dbf0e22eca3 100644 --- a/chromium/ui/gl/init/create_gr_gl_interface.cc +++ b/chromium/ui/gl/init/create_gr_gl_interface.cc @@ -552,34 +552,6 @@ sk_sp CreateGrGLInterface( functions->fBlitFramebuffer = bind_with_flush_on_mac(gl->glBlitFramebufferFn, version_info.is_angle); - functions->fMatrixLoadf = gl->glMatrixLoadfEXTFn; - functions->fMatrixLoadIdentity = gl->glMatrixLoadIdentityEXTFn; - functions->fPathCommands = gl->glPathCommandsNVFn; - functions->fPathParameteri = gl->glPathParameteriNVFn; - functions->fPathParameterf = gl->glPathParameterfNVFn; - functions->fGenPaths = gl->glGenPathsNVFn; - functions->fDeletePaths = gl->glDeletePathsNVFn; - functions->fIsPath = gl->glIsPathNVFn; - functions->fPathStencilFunc = gl->glPathStencilFuncNVFn; - functions->fStencilFillPath = gl->glStencilFillPathNVFn; - functions->fStencilStrokePath = gl->glStencilStrokePathNVFn; - functions->fStencilFillPathInstanced = gl->glStencilFillPathInstancedNVFn; - functions->fStencilStrokePathInstanced = gl->glStencilStrokePathInstancedNVFn; - functions->fCoverFillPath = gl->glCoverFillPathNVFn; - functions->fCoverStrokePath = gl->glCoverStrokePathNVFn; - functions->fCoverFillPathInstanced = gl->glCoverFillPathInstancedNVFn; - functions->fCoverStrokePathInstanced = gl->glCoverStrokePathInstancedNVFn; - functions->fStencilThenCoverFillPath = gl->glStencilThenCoverFillPathNVFn; - functions->fStencilThenCoverStrokePath = gl->glStencilThenCoverStrokePathNVFn; - functions->fStencilThenCoverFillPathInstanced = - gl->glStencilThenCoverFillPathInstancedNVFn; - functions->fStencilThenCoverStrokePathInstanced = - gl->glStencilThenCoverStrokePathInstancedNVFn; - functions->fProgramPathFragmentInputGen = - gl->glProgramPathFragmentInputGenNVFn; - functions->fBindFragmentInputLocation = - gl->glBindFragmentInputLocationCHROMIUMFn; - functions->fCoverageModulation = gl->glCoverageModulationNVFn; functions->fInsertEventMarker = gl->glInsertEventMarkerEXTFn; @@ -595,8 +567,6 @@ sk_sp CreateGrGLInterface( functions->fInvalidateFramebuffer = gl->glInvalidateFramebufferFn; functions->fInvalidateSubFramebuffer = gl->glInvalidateSubFramebufferFn; - functions->fGetProgramResourceLocation = gl->glGetProgramResourceLocationFn; - // GL_NV_bindless_texture // functions->fGetTextureHandle = gl->glGetTextureHandleNVFn; // functions->fGetTextureSamplerHandle = gl->glGetTextureSamplerHandleNVFn; diff --git a/chromium/ui/gl/init/gl_factory.cc b/chromium/ui/gl/init/gl_factory.cc index facdc5a4775..ddb538a4ed3 100644 --- a/chromium/ui/gl/init/gl_factory.cc +++ b/chromium/ui/gl/init/gl_factory.cc @@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" @@ -26,23 +27,26 @@ bool g_is_angle_enabled = true; bool ShouldFallbackToSoftwareGL() { const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); - std::string requested_implementation_name = + std::string requested_implementation_gl_name = cmd->GetSwitchValueASCII(switches::kUseGL); if (cmd->HasSwitch(switches::kUseGL) && - requested_implementation_name == "any") { + requested_implementation_gl_name == "any") { return true; } else { return false; } } -GLImplementation GetRequestedGLImplementation(bool* fallback_to_software_gl) { +GLImplementationParts GetRequestedGLImplementation( + bool* fallback_to_software_gl) { const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); - std::string requested_implementation_name = + std::string requested_implementation_gl_name = cmd->GetSwitchValueASCII(switches::kUseGL); - if (requested_implementation_name == kGLImplementationDisabledName) { - return gl::kGLImplementationDisabled; + std::string requested_implementation_angle_name = + cmd->GetSwitchValueASCII(switches::kUseANGLE); + if (requested_implementation_gl_name == kGLImplementationDisabledName) { + return GLImplementationParts(kGLImplementationDisabled); } std::vector allowed_impls = GetAllowedGLImplementations(); @@ -70,31 +74,37 @@ GLImplementation GetRequestedGLImplementation(bool* fallback_to_software_gl) { if (allowed_impls.empty()) { LOG(ERROR) << "List of allowed GL implementations is empty."; - return kGLImplementationNone; + return GLImplementationParts(kGLImplementationNone); } // The default implementation is always the first one in list. - GLImplementation impl = allowed_impls[0]; + GLImplementationParts impl = GLImplementationParts(allowed_impls[0]); + UMA_HISTOGRAM_ENUMERATION("GPU.PreferredGLImplementation", impl.gl); + *fallback_to_software_gl = false; if (cmd->HasSwitch(switches::kOverrideUseSoftwareGLForTests)) { - impl = GetSoftwareGLImplementation(); + impl = GetSoftwareGLForTestsImplementation(); } else if (cmd->HasSwitch(switches::kUseGL)) { - if (requested_implementation_name == "any") { + if (requested_implementation_gl_name == "any") { *fallback_to_software_gl = true; - } else if ((requested_implementation_name == + } else if ((requested_implementation_gl_name == kGLImplementationSwiftShaderName) || - (requested_implementation_name == + (requested_implementation_gl_name == kGLImplementationSwiftShaderForWebGLName)) { - impl = kGLImplementationSwiftShaderGL; + impl = GLImplementationParts(kGLImplementationSwiftShaderGL); } else { - impl = GetNamedGLImplementation(requested_implementation_name); - if (!base::Contains(allowed_impls, impl)) { + impl = GetNamedGLImplementation(requested_implementation_gl_name, + requested_implementation_angle_name); + if (!base::Contains(allowed_impls, impl.gl)) { LOG(ERROR) << "Requested GL implementation is not available."; - return kGLImplementationNone; + UMA_HISTOGRAM_ENUMERATION("GPU.RequestedGLImplementation", + kGLImplementationNone); + return GLImplementationParts(kGLImplementationNone); } } } + UMA_HISTOGRAM_ENUMERATION("GPU.RequestedGLImplementation", impl.gl); return impl; } @@ -140,12 +150,12 @@ bool InitializeStaticGLBindingsOneOff() { DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); bool fallback_to_software_gl = false; - GLImplementation impl = + GLImplementationParts impl = GetRequestedGLImplementation(&fallback_to_software_gl); - if (impl == gl::kGLImplementationDisabled) { + if (impl.gl == gl::kGLImplementationDisabled) { gl::SetGLImplementation(gl::kGLImplementationDisabled); return true; - } else if (impl == gl::kGLImplementationNone) { + } else if (impl.gl == gl::kGLImplementationNone) { return false; } @@ -153,15 +163,16 @@ bool InitializeStaticGLBindingsOneOff() { fallback_to_software_gl); } -bool InitializeStaticGLBindingsImplementation(GLImplementation impl, +bool InitializeStaticGLBindingsImplementation(GLImplementationParts impl, bool fallback_to_software_gl) { - if (impl == GetSoftwareGLImplementation()) + if (IsSoftwareGLImplementation(impl)) fallback_to_software_gl = false; bool initialized = InitializeStaticGLBindings(impl); if (!initialized && fallback_to_software_gl) { ShutdownGL(/*due_to_fallback*/ true); - initialized = InitializeStaticGLBindings(GetSoftwareGLImplementation()); + initialized = + InitializeStaticGLBindings(GetLegacySoftwareGLImplementation()); } if (!initialized) { ShutdownGL(/*due_to_fallback*/ false); @@ -173,14 +184,15 @@ bool InitializeStaticGLBindingsImplementation(GLImplementation impl, bool InitializeGLOneOffPlatformImplementation(bool fallback_to_software_gl, bool disable_gl_drawing, bool init_extensions) { - if (GetGLImplementation() == GetSoftwareGLImplementation()) + if (IsSoftwareGLImplementation(GetGLImplementationParts())) fallback_to_software_gl = false; bool initialized = InitializeGLOneOffPlatform(); if (!initialized && fallback_to_software_gl) { ShutdownGL(/*due_to_fallback*/ true); - initialized = InitializeStaticGLBindings(GetSoftwareGLImplementation()) && - InitializeGLOneOffPlatform(); + initialized = + InitializeStaticGLBindings(GetLegacySoftwareGLImplementation()) && + InitializeGLOneOffPlatform(); } if (initialized && init_extensions) { initialized = InitializeExtensionSettingsOneOffPlatform(); @@ -190,7 +202,8 @@ bool InitializeGLOneOffPlatformImplementation(bool fallback_to_software_gl, ShutdownGL(false); if (initialized) { - DVLOG(1) << "Using " << GetGLImplementationName(GetGLImplementation()) + DVLOG(1) << "Using " + << GetGLImplementationGLName(GetGLImplementationParts()) << " GL implementation."; if (disable_gl_drawing) InitializeNullDrawGLBindings(); diff --git a/chromium/ui/gl/init/gl_factory.h b/chromium/ui/gl/init/gl_factory.h index 43028f7b43e..58a77d856ff 100644 --- a/chromium/ui/gl/init/gl_factory.h +++ b/chromium/ui/gl/init/gl_factory.h @@ -49,7 +49,7 @@ GL_INIT_EXPORT bool InitializeExtensionSettingsOneOffPlatform(); // Initializes GL bindings using the provided parameters. This might be required // for use in tests. GL_INIT_EXPORT bool InitializeStaticGLBindingsImplementation( - GLImplementation impl, + GLImplementationParts impl, bool fallback_to_software_gl); // Initializes GL platform using the provided parameters. This might be required diff --git a/chromium/ui/gl/init/gl_initializer.h b/chromium/ui/gl/init/gl_initializer.h index 4fa188883f9..95a5a55c195 100644 --- a/chromium/ui/gl/init/gl_initializer.h +++ b/chromium/ui/gl/init/gl_initializer.h @@ -21,7 +21,7 @@ namespace init { bool InitializeGLOneOffPlatform(); // Initializes a particular GL implementation. -bool InitializeStaticGLBindings(GLImplementation implementation); +bool InitializeStaticGLBindings(GLImplementationParts implementation); #if BUILDFLAG(USE_STATIC_ANGLE) bool InitializeStaticANGLEEGL(); diff --git a/chromium/ui/gl/init/gl_initializer_android.cc b/chromium/ui/gl/init/gl_initializer_android.cc index d1c269e9c91..175fd82d463 100644 --- a/chromium/ui/gl/init/gl_initializer_android.cc +++ b/chromium/ui/gl/init/gl_initializer_android.cc @@ -48,12 +48,12 @@ bool InitializeStaticNativeEGLInternal() { return true; } -bool InitializeStaticEGLInternal(GLImplementation implementation) { +bool InitializeStaticEGLInternal(GLImplementationParts implementation) { bool initialized = false; #if BUILDFLAG(USE_STATIC_ANGLE) // Use ANGLE if it is requested and it is statically linked - if (implementation == kGLImplementationEGLANGLE) { + if (implementation.gl == kGLImplementationEGLANGLE) { initialized = InitializeStaticANGLEEGL(); } #endif // BUILDFLAG(USE_STATIC_ANGLE) @@ -66,7 +66,7 @@ bool InitializeStaticEGLInternal(GLImplementation implementation) { return false; } - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); InitializeStaticGLBindingsEGL(); @@ -91,19 +91,19 @@ bool InitializeGLOneOffPlatform() { } } -bool InitializeStaticGLBindings(GLImplementation implementation) { +bool InitializeStaticGLBindings(GLImplementationParts implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); - switch (implementation) { + switch (implementation.gl) { case kGLImplementationEGLGLES2: case kGLImplementationEGLANGLE: return InitializeStaticEGLInternal(implementation); case kGLImplementationMockGL: case kGLImplementationStubGL: - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); return true; default: diff --git a/chromium/ui/gl/init/gl_initializer_linux_x11.cc b/chromium/ui/gl/init/gl_initializer_linux_x11.cc index b1f21c4bf0e..016046d6caa 100644 --- a/chromium/ui/gl/init/gl_initializer_linux_x11.cc +++ b/chromium/ui/gl/init/gl_initializer_linux_x11.cc @@ -134,26 +134,22 @@ bool InitializeStaticEGLInternalFromLibrary(GLImplementation implementation) { return true; } -bool InitializeStaticEGLInternal(GLImplementation implementation) { +bool InitializeStaticEGLInternal(GLImplementationParts implementation) { #if BUILDFLAG(USE_STATIC_ANGLE) - if (implementation == kGLImplementationEGLANGLE) { + if (implementation.gl == kGLImplementationEGLANGLE) { // Use ANGLE if it is requested and it is statically linked if (!InitializeStaticANGLEEGL()) return false; - } else if (!InitializeStaticEGLInternalFromLibrary(implementation)) { + } else if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) { return false; } #else - if (!InitializeStaticEGLInternalFromLibrary(implementation)) { + if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) { return false; } #endif // !BUILDFLAG(USE_STATIC_ANGLE) - if (implementation == kGLImplementationEGLANGLE) { - SetGLImplementation(kGLImplementationEGLANGLE); - } else { - SetGLImplementation(kGLImplementationEGLGLES2); - } + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); InitializeStaticGLBindingsEGL(); @@ -188,7 +184,7 @@ bool InitializeGLOneOffPlatformX11() { } } -bool InitializeStaticGLBindingsX11(GLImplementation implementation) { +bool InitializeStaticGLBindingsX11(GLImplementationParts implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. @@ -200,7 +196,7 @@ bool InitializeStaticGLBindingsX11(GLImplementation implementation) { // one-time initialization cost is small, between 2 and 5 ms. base::ThreadRestrictions::ScopedAllowIO allow_io; - switch (implementation) { + switch (implementation.gl) { case kGLImplementationDesktopGL: return InitializeStaticGLXInternal(); case kGLImplementationSwiftShaderGL: @@ -209,7 +205,7 @@ bool InitializeStaticGLBindingsX11(GLImplementation implementation) { return InitializeStaticEGLInternal(implementation); case kGLImplementationMockGL: case kGLImplementationStubGL: - SetGLImplementation(implementation); + SetGLImplementation(implementation.gl); InitializeStaticGLBindingsGL(); return true; default: diff --git a/chromium/ui/gl/init/gl_initializer_linux_x11.h b/chromium/ui/gl/init/gl_initializer_linux_x11.h index 07e0f8654de..202054b0319 100644 --- a/chromium/ui/gl/init/gl_initializer_linux_x11.h +++ b/chromium/ui/gl/init/gl_initializer_linux_x11.h @@ -26,7 +26,7 @@ namespace init { bool InitializeGLOneOffPlatformX11(); // Initializes a particular GL implementation. -bool InitializeStaticGLBindingsX11(GLImplementation implementation); +bool InitializeStaticGLBindingsX11(GLImplementationParts implementation); // Clears GL bindings for all implementations supported by platform. void ShutdownGLPlatformX11(); diff --git a/chromium/ui/gl/init/gl_initializer_mac.cc b/chromium/ui/gl/init/gl_initializer_mac.cc index f659291023a..98f3c5a43da 100644 --- a/chromium/ui/gl/init/gl_initializer_mac.cc +++ b/chromium/ui/gl/init/gl_initializer_mac.cc @@ -159,22 +159,22 @@ bool InitializeStaticEGLInternalFromLibrary(GLImplementation implementation) { return true; } -bool InitializeStaticEGLInternal(GLImplementation implementation) { +bool InitializeStaticEGLInternal(GLImplementationParts implementation) { #if BUILDFLAG(USE_STATIC_ANGLE) - if (implementation == kGLImplementationEGLANGLE) { + if (implementation.gl == kGLImplementationEGLANGLE) { // Use ANGLE if it is requested and it is statically linked if (!InitializeStaticANGLEEGL()) return false; - } else if (!InitializeStaticEGLInternalFromLibrary(implementation)) { + } else if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) { return false; } #else - if (!InitializeStaticEGLInternalFromLibrary(implementation)) { + if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) { return false; } #endif // !BUILDFLAG(USE_STATIC_ANGLE) - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); InitializeStaticGLBindingsEGL(); @@ -209,7 +209,7 @@ bool InitializeGLOneOffPlatform() { } } -bool InitializeStaticGLBindings(GLImplementation implementation) { +bool InitializeStaticGLBindings(GLImplementationParts implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. @@ -221,11 +221,11 @@ bool InitializeStaticGLBindings(GLImplementation implementation) { // one-time initialization cost is small, between 2 and 5 ms. base::ThreadRestrictions::ScopedAllowIO allow_io; - switch (implementation) { + switch (implementation.gl) { case kGLImplementationDesktopGL: case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: - return InitializeStaticCGLInternal(implementation); + return InitializeStaticCGLInternal(implementation.gl); #if defined(USE_EGL) case kGLImplementationEGLGLES2: case kGLImplementationEGLANGLE: @@ -234,7 +234,7 @@ bool InitializeStaticGLBindings(GLImplementation implementation) { #endif // #if defined(USE_EGL) case kGLImplementationMockGL: case kGLImplementationStubGL: - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); return true; default: diff --git a/chromium/ui/gl/init/gl_initializer_ozone.cc b/chromium/ui/gl/init/gl_initializer_ozone.cc index aac4833f6c9..17c5e262164 100644 --- a/chromium/ui/gl/init/gl_initializer_ozone.cc +++ b/chromium/ui/gl/init/gl_initializer_ozone.cc @@ -47,7 +47,7 @@ bool InitializeGLOneOffPlatform() { return false; } -bool InitializeStaticGLBindings(GLImplementation implementation) { +bool InitializeStaticGLBindings(GLImplementationParts implementation) { #if defined(USE_X11) if (!features::IsUsingOzonePlatform()) return gl::init::InitializeStaticGLBindingsX11(implementation); @@ -64,10 +64,10 @@ bool InitializeStaticGLBindings(GLImplementation implementation) { ->InitializeStaticGLBindings(implementation); } - switch (implementation) { + switch (implementation.gl) { case kGLImplementationMockGL: case kGLImplementationStubGL: - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); return true; default: diff --git a/chromium/ui/gl/init/gl_initializer_win.cc b/chromium/ui/gl/init/gl_initializer_win.cc index 8e3b73b0642..dae3a193e77 100644 --- a/chromium/ui/gl/init/gl_initializer_win.cc +++ b/chromium/ui/gl/init/gl_initializer_win.cc @@ -109,22 +109,22 @@ bool InitializeStaticEGLInternalFromLibrary(GLImplementation implementation) { return true; } -bool InitializeStaticEGLInternal(GLImplementation implementation) { +bool InitializeStaticEGLInternal(GLImplementationParts implementation) { #if BUILDFLAG(USE_STATIC_ANGLE) - if (implementation == kGLImplementationEGLANGLE) { + if (implementation.gl == kGLImplementationEGLANGLE) { // Use ANGLE if it is requested and it is statically linked if (!InitializeStaticANGLEEGL()) return false; - } else if (!InitializeStaticEGLInternalFromLibrary(implementation)) { + } else if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) { return false; } #else - if (!InitializeStaticEGLInternalFromLibrary(implementation)) { + if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) { return false; } #endif // !BUILDFLAG(USE_STATIC_ANGLE) - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); InitializeStaticGLBindingsEGL(); @@ -153,7 +153,7 @@ bool InitializeGLOneOffPlatform() { return true; } -bool InitializeStaticGLBindings(GLImplementation implementation) { +bool InitializeStaticGLBindings(GLImplementationParts implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. @@ -165,13 +165,13 @@ bool InitializeStaticGLBindings(GLImplementation implementation) { // one-time initialization cost is small, between 2 and 5 ms. base::ThreadRestrictions::ScopedAllowIO allow_io; - switch (implementation) { + switch (implementation.gl) { case kGLImplementationSwiftShaderGL: case kGLImplementationEGLANGLE: return InitializeStaticEGLInternal(implementation); case kGLImplementationMockGL: case kGLImplementationStubGL: - SetGLImplementation(implementation); + SetGLImplementationParts(implementation); InitializeStaticGLBindingsGL(); return true; default: diff --git a/chromium/ui/gl/init/ozone_util.h b/chromium/ui/gl/init/ozone_util.h index 11c04d0c7e7..93da0c2a9d2 100644 --- a/chromium/ui/gl/init/ozone_util.h +++ b/chromium/ui/gl/init/ozone_util.h @@ -19,24 +19,24 @@ inline ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() { } // Returns true if there is an GLOzone for the specified GL implementation. -inline bool HasGLOzone(GLImplementation impl) { +inline bool HasGLOzone(const GLImplementationParts& impl) { return GetSurfaceFactoryOzone() && GetSurfaceFactoryOzone()->GetGLOzone(impl); } // Returns true if there is an GLOzone for the set GL implementation. inline bool HasGLOzone() { - return HasGLOzone(GetGLImplementation()); + return HasGLOzone(GetGLImplementationParts()); } // Returns the GLOzone for the specified GL implementation or null if none // exists. -inline ui::GLOzone* GetGLOzone(GLImplementation impl) { +inline ui::GLOzone* GetGLOzone(const GLImplementationParts& impl) { return GetSurfaceFactoryOzone()->GetGLOzone(impl); } // Returns the GLOzone for the set GL implementation or null if none exists. inline ui::GLOzone* GetGLOzone() { - return GetGLOzone(GetGLImplementation()); + return GetGLOzone(GetGLImplementationParts()); } } // namespace init diff --git a/chromium/ui/gl/swap_chain_presenter.cc b/chromium/ui/gl/swap_chain_presenter.cc index bc8f30d0198..6889bc6fbb6 100644 --- a/chromium/ui/gl/swap_chain_presenter.cc +++ b/chromium/ui/gl/swap_chain_presenter.cc @@ -12,8 +12,10 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" +#include "media/base/win/mf_helpers.h" #include "ui/gfx/color_space_win.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gl/dc_layer_tree.h" @@ -168,6 +170,32 @@ void UpdateSwapChainTransform(const gfx::Size& quad_size, transform->Scale(swap_chain_scale_x, swap_chain_scale_y); } +void LabelSwapChainBuffers(IDXGISwapChain* swap_chain) { + DXGI_SWAP_CHAIN_DESC desc; + HRESULT hr = swap_chain->GetDesc(&desc); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to GetDesc from swap chain: " + << logging::SystemErrorCodeToString(hr); + return; + } + for (unsigned int i = 0; i < desc.BufferCount; i++) { + Microsoft::WRL::ComPtr swap_chain_buffer; + hr = swap_chain->GetBuffer(i, IID_PPV_ARGS(&swap_chain_buffer)); + if (FAILED(hr)) { + DLOG(ERROR) << "GetBuffer on swap chain buffer " << i + << "failed: " << logging::SystemErrorCodeToString(hr); + return; + } + hr = media::SetDebugName( + swap_chain_buffer.Get(), + base::StringPrintf("SwapChainPresenter_Buffer_%d", i).c_str()); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to label swap chain buffer " << i << ": " + << logging::SystemErrorCodeToString(hr); + } + } +} + } // namespace SwapChainPresenter::PresentationHistory::PresentationHistory() = default; @@ -209,34 +237,29 @@ SwapChainPresenter::SwapChainPresenter( window_(window), d3d11_device_(d3d11_device), dcomp_device_(dcomp_device), - is_on_battery_power_(true) { - if (base::PowerMonitor::IsInitialized()) { - is_on_battery_power_ = base::PowerMonitor::IsOnBatteryPower(); - base::PowerMonitor::AddObserver(this); - } -} + is_on_battery_power_( + base::PowerMonitor::AddPowerStateObserverAndReturnOnBatteryState( + this)) {} SwapChainPresenter::~SwapChainPresenter() { - base::PowerMonitor::RemoveObserver(this); + base::PowerMonitor::RemovePowerStateObserver(this); } DXGI_FORMAT SwapChainPresenter::GetSwapChainFormat( gfx::ProtectedVideoType protected_video_type, bool content_is_hdr) { + // Prefer RGB10A2 swapchain when playing HDR content. + if (content_is_hdr) + return DXGI_FORMAT_R10G10B10A2_UNORM; + DXGI_FORMAT yuv_overlay_format = DirectCompositionSurfaceWin::GetOverlayFormatUsedForSDR(); - // TODO(crbug.com/850799): Assess power/perf impact when protected video - // swap chain is composited by DWM. - // Always prefer YUV swap chain for hardware protected video for now. if (protected_video_type == gfx::ProtectedVideoType::kHardwareProtected) return yuv_overlay_format; - // Prefer RGB10A2 swapchain when playing HDR content. - if (content_is_hdr) - return DXGI_FORMAT_R10G10B10A2_UNORM; - - if (failed_to_create_yuv_swapchain_) + if (failed_to_create_yuv_swapchain_ || + !DirectCompositionSurfaceWin::AreHardwareOverlaysSupported()) return DXGI_FORMAT_B8G8R8A8_UNORM; // Start out as YUV. @@ -309,6 +332,11 @@ Microsoft::WRL::ComPtr SwapChainPresenter::UploadVideoImages( } DCHECK(staging_texture_); staging_texture_size_ = texture_size; + hr = media::SetDebugName(staging_texture_.Get(), + "SwapChainPresenter_Staging"); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to label D3D11 texture: " << std::hex << hr; + } } Microsoft::WRL::ComPtr context; @@ -363,6 +391,10 @@ Microsoft::WRL::ComPtr SwapChainPresenter::UploadVideoImages( return nullptr; } DCHECK(copy_texture_); + hr = media::SetDebugName(copy_texture_.Get(), "SwapChainPresenter_Copy"); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to label D3D11 texture: " << std::hex << hr; + } } TRACE_EVENT0("gpu", "SwapChainPresenter::UploadVideoImages::CopyResource"); context->CopyResource(copy_texture_.Get(), staging_texture_.Get()); @@ -1349,7 +1381,7 @@ bool SwapChainPresenter::ReallocateSwapChain( TRACE_EVENT0("gpu", trace_event_stream.str().c_str()); desc.Format = swap_chain_format; - desc.Flags = 0; + desc.Flags = DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO; if (IsProtectedVideo(protected_video_type)) desc.Flags |= DXGI_SWAP_CHAIN_FLAG_DISPLAY_ONLY; if (protected_video_type == gfx::ProtectedVideoType::kHardwareProtected) @@ -1380,6 +1412,7 @@ bool SwapChainPresenter::ReallocateSwapChain( return false; } } + LabelSwapChainBuffers(swap_chain_.Get()); swap_chain_format_ = swap_chain_format; SetSwapChainPresentDuration(); return true; diff --git a/chromium/ui/gl/swap_chain_presenter.h b/chromium/ui/gl/swap_chain_presenter.h index 6ecd03e9ae1..c93bbcab4c8 100644 --- a/chromium/ui/gl/swap_chain_presenter.h +++ b/chromium/ui/gl/swap_chain_presenter.h @@ -24,7 +24,7 @@ class GLImageMemory; // SwapChainPresenter holds a swap chain, direct composition visuals, and other // associated resources for a single overlay layer. It is updated by calling // PresentToSwapChain(), and can update or recreate resources as necessary. -class SwapChainPresenter : public base::PowerObserver { +class SwapChainPresenter : public base::PowerStateObserver { public: SwapChainPresenter(DCLayerTree* layer_tree, HWND window, @@ -176,7 +176,7 @@ class SwapChainPresenter : public base::PowerObserver { // decode swap chain. void RecordPresentationStatistics(); - // base::PowerObserver + // base::PowerStateObserver void OnPowerStateChange(bool on_battery_power) override; // If connected with a power source, let the Intel video processor to do diff --git a/chromium/ui/gtk/BUILD.gn b/chromium/ui/gtk/BUILD.gn index 447f77309fb..47ec07c887d 100644 --- a/chromium/ui/gtk/BUILD.gn +++ b/chromium/ui/gtk/BUILD.gn @@ -2,9 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -assert(is_linux || is_chromeos_lacros || is_chromeos, - "This file should only be referenced on Linux") - import("//build/buildflag_header.gni") import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") @@ -12,19 +9,39 @@ import("//build/config/linux/gtk/gtk.gni") import("//build/config/ozone.gni") import("//build/config/ui.gni") import("//printing/buildflags/buildflags.gni") +import("//testing/test.gni") 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" ] } -generate_stubs("gdk_pixbuf") { - sigs = [ "gdk_pixbuf.sigs" ] - extra_header = "gdk_pixbuf.fragment" - output_name = "gdk_pixbuf" - deps = [ "//build/config/linux/gtk" ] +source_set("gtk_types") { + sources = [ "gtk_types.h" ] + deps = [ ":gtk_buildflags" ] +} + +generate_stubs("gtk_stubs") { + sigs = [ + "gdk_pixbuf.sigs", + "gdk.sigs", + "gsk.sigs", + "gtk.sigs", + "gio.sigs", + ] + extra_header = "gtk.fragment" + output_name = "gtk_stubs" + deps = [ + ":gtk_types", + "//build/config/linux/gtk", + ] + logging_function = "LogNoop()" + logging_include = "ui/gtk/log_noop.h" } component("gtk_ui_delegate") { @@ -40,7 +57,14 @@ component("gtk_ui_delegate") { component("gtk") { public = [ "gtk_ui.h" ] + + friend = [ ":gtk_unittests" ] + sources = [ + "gtk_color_mixers.cc", + "gtk_color_mixers.h", + "gtk_compat.cc", + "gtk_compat.h", "gtk_key_bindings_handler.cc", "gtk_key_bindings_handler.h", "gtk_ui.cc", @@ -80,7 +104,8 @@ component("gtk") { } deps = [ - ":gdk_pixbuf", + ":gtk_stubs", + ":gtk_types", "//base", "//build/config/linux/gtk:gtkprint", "//printing", @@ -97,6 +122,8 @@ component("gtk") { "//ui/base/cursor:theme_manager", "//ui/base/ime", "//ui/base/ime/linux", + "//ui/color", + "//ui/color:mixers", "//ui/display", "//ui/events", "//ui/events:dom_keyboard_layout", @@ -121,3 +148,20 @@ component("gtk") { deps += [ "//ui/ozone" ] } } + +test("gtk_unittests") { + sources = [ "native_theme_gtk_unittest.cc" ] + + deps = [ + ":gtk", + "//base/test:run_all_unittests", + "//base/test:test_support", + + # Required so that including gtk_util.h can resolve . + "//build/config/linux/gtk", + "//testing/gtest", + "//ui/base:features", + "//ui/native_theme", + "//ui/native_theme:test_support", + ] +} diff --git a/chromium/ui/gtk/DEPS b/chromium/ui/gtk/DEPS index 0684a68d918..51f523c4958 100644 --- a/chromium/ui/gtk/DEPS +++ b/chromium/ui/gtk/DEPS @@ -4,6 +4,7 @@ include_rules = [ "+third_party/skia", "+ui/aura", "+ui/base", + "+ui/color", "+ui/display", "+ui/events", "+ui/gfx", diff --git a/chromium/ui/gtk/gdk.sigs b/chromium/ui/gtk/gdk.sigs new file mode 100644 index 00000000000..a2170ffd40d --- /dev/null +++ b/chromium/ui/gtk/gdk.sigs @@ -0,0 +1,20 @@ +GdkDisplay* gdk_display_get_default(void); +gboolean gdk_keymap_translate_keyboard_state(GdkKeymap* keymap, guint hardware_keycode, GdkModifierType state, gint group, guint* keyval, gint* effective_group, gint* level, GdkModifierType* consumed_modifiers); +void gdk_keymap_add_virtual_modifiers(GdkKeymap* keymap, GdkModifierType* state); +GdkEvent* gdk_event_new(GdkEventType type); +void gdk_event_free(GdkEvent* event); +gboolean gdk_keymap_get_entries_for_keycode(GdkKeymap* keymap, guint hardware_keycode, GdkKeymapKey** keys, guint** keyvals, gint* n_entries); +GdkKeymap* gdk_keymap_get_for_display(GdkDisplay* display); +int gdk_texture_get_width(GdkTexture* texture); +int gdk_texture_get_height(GdkTexture* texture); +void gdk_texture_download(GdkTexture* texture, guchar* data, gsize stride); +gboolean gdk_display_map_keycode(GdkDisplay* display, guint keycode, GdkKeymapKey** keys, guint** keyvals, int* n_entries); +void gdk_paintable_snapshot(GdkPaintable* paintable, GdkSnapshot* snapshot, double width, double height); +GType gdk_paintable_get_type(void); +GdkSeat* gdk_display_get_default_seat(GdkDisplay* display); +GdkDevice* gdk_seat_get_keyboard(GdkSeat* seat); +GdkTexture* gdk_memory_texture_new(int width, int height, GdkMemoryFormat format, GBytes* bytes, gsize stride); +int gdk_paintable_get_intrinsic_width(GdkPaintable* paintable); +int gdk_paintable_get_intrinsic_height(GdkPaintable* paintable); +GdkScreen* gdk_screen_get_default(void); +gdouble gdk_screen_get_resolution(GdkScreen *screen); diff --git a/chromium/ui/gtk/gdk_pixbuf.fragment b/chromium/ui/gtk/gdk_pixbuf.fragment deleted file mode 100644 index 99e4ea2ecb9..00000000000 --- a/chromium/ui/gtk/gdk_pixbuf.fragment +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/chromium/ui/gtk/gio.sigs b/chromium/ui/gtk/gio.sigs new file mode 100644 index 00000000000..01f6bde43c9 --- /dev/null +++ b/chromium/ui/gtk/gio.sigs @@ -0,0 +1,4 @@ +const char* g_file_peek_path(GFile* file); +gpointer g_list_model_get_item(GListModel* list, guint position); +guint g_list_model_get_n_items(GListModel* list); +GObject* g_list_model_get_object(GListModel* list, guint position); diff --git a/chromium/ui/gtk/gsk.sigs b/chromium/ui/gtk/gsk.sigs new file mode 100644 index 00000000000..4f3a8650fb7 --- /dev/null +++ b/chromium/ui/gtk/gsk.sigs @@ -0,0 +1,16 @@ +GskRenderNodeType gsk_render_node_get_node_type(GskRenderNode* node); +void gsk_render_node_unref(GskRenderNode* node); +GskRenderNode* gsk_transform_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_opacity_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_color_matrix_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_repeat_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_clip_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_rounded_clip_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_shadow_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_blur_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_debug_node_get_child(GskRenderNode* node); +GskRenderNode* gsk_container_node_get_child(GskRenderNode* node, guint idx); +GskRenderNode* gsk_gl_shader_node_get_child(GskRenderNode* node, guint idx); +guint gsk_container_node_get_n_children(GskRenderNode* node); +guint gsk_gl_shader_node_get_n_children(GskRenderNode* node); +GdkTexture* gsk_texture_node_get_texture(GskRenderNode* node); diff --git a/chromium/ui/gtk/gtk.fragment b/chromium/ui/gtk/gtk.fragment new file mode 100644 index 00000000000..4a0b78caf2e --- /dev/null +++ b/chromium/ui/gtk/gtk.fragment @@ -0,0 +1 @@ +#include "ui/gtk/gtk_compat.h" diff --git a/chromium/ui/gtk/gtk.sigs b/chromium/ui/gtk/gtk.sigs new file mode 100644 index 00000000000..39dd8f1e29d --- /dev/null +++ b/chromium/ui/gtk/gtk.sigs @@ -0,0 +1,54 @@ +GtkSettings* gtk_settings_get_default(void); +void gtk_widget_path_iter_set_object_name(GtkWidgetPath* path, gint pos, const gchar* name); +void gtk_widget_path_iter_add_class(GtkWidgetPath* path, gint pos, const gchar* name); +GtkWidgetPath* gtk_widget_path_copy(const GtkWidgetPath* path); +GtkWidgetPath* gtk_widget_path_new(void); +const GtkWidgetPath* gtk_style_context_get_path(GtkStyleContext* context); +gint gtk_widget_path_append_type(GtkWidgetPath* path, GType type); +void gtk_widget_path_iter_set_name(GtkWidgetPath* path, gint pos, const gchar* name); +void gtk_widget_path_iter_set_state(GtkWidgetPath* path, gint pos, GtkStateFlags state); +GtkStyleContext* gtk_style_context_new(void); +void gtk_style_context_set_path(GtkStyleContext* context, GtkWidgetPath* path); +void gtk_style_context_set_parent(GtkStyleContext* context, GtkStyleContext* parent); +void gtk_widget_path_unref(GtkWidgetPath* path); +GtkStyleContext* gtk_style_context_get_parent(GtkStyleContext* context); +void gtk_widget_set_css_classes(GtkWidget* widget, const char** classes); +void gtk_widget_measure(GtkWidget* widget, GtkOrientation orientation, int for_size, int* minimum, int* natural, int* minimum_baseline, int* natural_baseline); +GtkWidget* gtk_offscreen_window_new(void); +void gtk_container_add(GtkContainer* container, GtkWidget* widget); +void gtk_widget_destroy(GtkWidget* widget); +gboolean gtk_bindings_activate_event(GObject* object, GdkEventKey* event); +void gtk_widget_set_events(GtkWidget* widget, gint events); +GType gtk_container_get_type(void); +cairo_surface_t* gtk_icon_info_load_surface(GtkIconInfo* icon_info, GdkWindow* for_window, GError** error); +void gtk_style_context_get_valist(GtkStyleContext* context, GtkStateFlags state, va_list args); +void gtk_style_context_get_style_valist(GtkStyleContext* context, va_list args); +GtkSnapshot* gtk_snapshot_new(void); +GskRenderNode* gtk_snapshot_free_to_node(GtkSnapshot* snapshot); +void gtk_im_context_set_client_widget(GtkIMContext* context, GtkWidget* widget); +GtkNative* gtk_widget_get_native(GtkWidget* widget); +GdkSurface* gtk_native_get_surface(GtkNative* native); +gboolean gtk_im_context_filter_key(GtkIMContext* context, gboolean press, GdkSurface* surface, GdkDevice* device, guint32 time, guint keycode, GdkModifierType state, int group); +void gtk_im_context_set_client_window(GtkIMContext* context, GdkWindow* window); +gboolean gtk_file_chooser_set_filename(GtkFileChooser* chooser, const char* filename); +GSList* gtk_file_chooser_list_filters(GtkFileChooser* chooser); +gchar* gtk_file_chooser_get_filename(GtkFileChooser* chooser); +GSList* gtk_file_chooser_get_filenames(GtkFileChooser* chooser); +char* gtk_file_chooser_get_preview_filename(GtkFileChooser* chooser); +void gtk_file_chooser_set_preview_widget_active(GtkFileChooser* chooser, gboolean active); +void gtk_file_chooser_set_preview_widget(GtkFileChooser* chooser, GtkWidget* preview_widget); +gboolean gtk_widget_hide_on_delete(GtkWidget* widget); +void gtk_widget_show_all(GtkWidget* widget); +void gtk_file_chooser_set_do_overwrite_confirmation(GtkFileChooser* chooser, gboolean do_overwrite_confirmation); +GListModel* gtk_file_chooser_get_filters(GtkFileChooser* chooser); +void gtk_window_set_hide_on_close(GtkWindow* window, gboolean setting); +GtkIconInfo* gtk_icon_theme_lookup_icon_for_scale(GtkIconTheme* icon_theme, const gchar* icon_name, gint size, gint scale, GtkIconLookupFlags flags); +GdkPixbuf* gtk_icon_info_load_symbolic_for_context(GtkIconInfo* icon_info, GtkStyleContext* context, gboolean* was_symbolic, GError** error); +void gtk_snapshot_render_background(GtkSnapshot* snapshot, GtkStyleContext* context, double x, double y, double width, double height); +GType gtk_menu_get_type(void); +GType gtk_menu_bar_get_type(void); +GType gtk_menu_item_get_type(void); +void gtk_style_context_add_provider_for_screen(GdkScreen* screen, GtkStyleProvider* provider, guint priority); +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); diff --git a/chromium/ui/gtk/gtk_color_mixers.cc b/chromium/ui/gtk/gtk_color_mixers.cc new file mode 100644 index 00000000000..044ddd4390c --- /dev/null +++ b/chromium/ui/gtk/gtk_color_mixers.cc @@ -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. + +#include "ui/gtk/gtk_color_mixers.h" + +#include "ui/color/color_id.h" +#include "ui/color/color_mixer.h" +#include "ui/color/color_provider.h" +#include "ui/color/color_recipe.h" +#include "ui/color/color_set.h" +#include "ui/color/color_transform.h" +#include "ui/gtk/gtk_util.h" + +namespace gtk { + +// TODO(tluk): The current GTK color mixer lifts the existing color definitions +// out of NativeThemeGtk. This mixer should leverage the hierarchical nature of +// color pipeline to reduce duplication of color definitions in +// `SkColorFromColorId()`. +void AddGtkNativeCoreColorMixer( + ui::ColorProvider* provider, + ui::ColorProviderManager::ColorMode color_mode, + ui::ColorProviderManager::ContrastMode contrast_mode) { + 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 color = gtk::SkColorFromColorId(id); + if (color) + color_map[id] = *color; + } + mixer.AddSet({ui::kColorSetNative, std::move(color_map)}); + + mixer[ui::kColorEndpointBackground] = + ui::GetColorWithMaxContrast(ui::kColorEndpointForeground); + mixer[ui::kColorEndpointForeground] = + ui::GetColorWithMaxContrast(ui::kColorWindowBackground); +} + +} // namespace gtk diff --git a/chromium/ui/gtk/gtk_color_mixers.h b/chromium/ui/gtk/gtk_color_mixers.h new file mode 100644 index 00000000000..3b4edb55e00 --- /dev/null +++ b/chromium/ui/gtk/gtk_color_mixers.h @@ -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. + +#ifndef UI_GTK_GTK_COLOR_MIXERS_H_ +#define UI_GTK_GTK_COLOR_MIXERS_H_ + +#include "ui/color/color_provider_manager.h" + +namespace ui { +class ColorProvider; +} // namespace ui + +namespace gtk { + +void AddGtkNativeCoreColorMixer( + ui::ColorProvider* provider, + ui::ColorProviderManager::ColorMode color_mode, + ui::ColorProviderManager::ContrastMode contrast_mode); + +} // namespace gtk + +#endif // UI_GTK_GTK_COLOR_MIXERS_H_ diff --git a/chromium/ui/gtk/gtk_compat.cc b/chromium/ui/gtk/gtk_compat.cc new file mode 100644 index 00000000000..0610d8aa5dd --- /dev/null +++ b/chromium/ui/gtk/gtk_compat.cc @@ -0,0 +1,282 @@ +// 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_compat.h" + +#include + +#include "base/check.h" +#include "base/compiler_specific.h" +#include "base/debug/leak_annotations.h" +#include "base/no_destructor.h" +#include "ui/gtk/gtk_stubs.h" + +namespace gtk { + +// IMPORTANT: All functions in this file that call dlsym()'ed +// functions should be annotated with DISABLE_CFI_ICALL. + +namespace { + +void* DlOpen(const char* library_name) { + void* library = dlopen(library_name, RTLD_LAZY | RTLD_GLOBAL); + CHECK(library); + return library; +} + +void* DlSym(void* library, const char* name) { + void* symbol = dlsym(library, name); + CHECK(symbol); + return symbol; +} + +template +auto DlCast(void* symbol) { + return reinterpret_cast(symbol); +} + +void* GetLibGio() { + static void* libgio = DlOpen("libgio-2.0.so.0"); + return libgio; +} + +void* GetLibGdkPixbuf() { + static void* libgdk_pixbuf = DlOpen("libgdk_pixbuf-2.0.so.0"); + return libgdk_pixbuf; +} + +void* GetLibGdk3() { + static void* libgdk3 = DlOpen("libgdk-3.so.0"); + return libgdk3; +} + +void* GetLibGtk3() { + static void* libgtk3 = DlOpen("libgtk-3.so.0"); + return libgtk3; +} + +void* GetLibGtk4() { + static void* libgtk4 = DlOpen("libgtk-4.so.1"); + return libgtk4; +} + +void* GetLibGtk() { + if (GtkCheckVersion(4)) + return GetLibGtk4(); + 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) { + ui_gtk::InitializeGdk_pixbuf(GetLibGdkPixbuf()); + ui_gtk::InitializeGdk(GetLibGdk3()); + ui_gtk::InitializeGtk(GetLibGtk3()); + } else { + // In GTK4 mode, we require some newer gio symbols that aren't available in + // Ubuntu Xenial or Debian Stretch. Fortunately, GTK4 itself depends on a + // newer version of glib (which provides gio), so if we're using GTK4, we + // can safely assume the system has the required gio symbols. + ui_gtk::InitializeGio(GetLibGio()); + // In GTK4, libgtk provides all gdk_*, gsk_*, and gtk_* symbols. + ui_gtk::InitializeGdk(GetLibGtk4()); + ui_gtk::InitializeGsk(GetLibGtk4()); + ui_gtk::InitializeGtk(GetLibGtk4()); + } + return true; +} + +const base::Version& GtkVersion() { + static base::NoDestructor gtk_version( + std::vector{gtk_get_major_version(), gtk_get_minor_version(), + gtk_get_micro_version()}); + return *gtk_version; +} + +bool GtkCheckVersion(int major, int minor, int micro) { + return GtkVersion() >= base::Version({major, minor, micro}); +} + +DISABLE_CFI_ICALL +void GtkInit(const std::vector& args) { + static void* gtk_init = DlSym(GetLibGtk(), "gtk_init"); + if (GtkCheckVersion(4)) { + DlCast(gtk_init)(); + } else { + // gtk_init() modifies argv, so make a copy first. + size_t args_chars = 0; + for (const auto& arg : args) + args_chars += arg.size() + 1; + std::vector args_copy(args_chars); + std::vector argv; + char* dst = args_copy.data(); + for (const auto& arg : args) { + argv.push_back(strcpy(dst, arg.c_str())); + dst += arg.size() + 1; + } + + int gtk_argc = argv.size(); + char** gtk_argv = argv.data(); + { + // http://crbug.com/423873 + ANNOTATE_SCOPED_MEMORY_LEAK; + DlCast(gtk_init)(>k_argc, >k_argv); + } + } +} + +DISABLE_CFI_ICALL +gfx::Insets GtkStyleContextGetPadding(GtkStyleContext* context) { + static void* get_padding = + DlSym(GetLibGtk(), "gtk_style_context_get_padding"); + GtkBorder padding; + if (GtkCheckVersion(4)) { + DlCast(get_padding)(context, &padding); + } else { + DlCast(get_padding)( + context, gtk_style_context_get_state(context), &padding); + } + return InsetsFromGtkBorder(padding); +} + +DISABLE_CFI_ICALL +gfx::Insets GtkStyleContextGetBorder(GtkStyleContext* context) { + static void* get_border = DlSym(GetLibGtk(), "gtk_style_context_get_border"); + GtkBorder border; + if (GtkCheckVersion(4)) { + DlCast(get_border)(context, &border); + } else { + DlCast(get_border)( + context, gtk_style_context_get_state(context), &border); + } + return InsetsFromGtkBorder(border); +} + +DISABLE_CFI_ICALL +gfx::Insets GtkStyleContextGetMargin(GtkStyleContext* context) { + static void* get_margin = DlSym(GetLibGtk(), "gtk_style_context_get_margin"); + GtkBorder margin; + if (GtkCheckVersion(4)) { + DlCast(get_margin)(context, &margin); + } else { + DlCast(get_margin)( + context, gtk_style_context_get_state(context), &margin); + } + return InsetsFromGtkBorder(margin); +} + +DISABLE_CFI_ICALL +bool GtkImContextFilterKeypress(GtkIMContext* context, GdkEventKey* event) { + static void* filter = DlSym(GetLibGtk(), "gtk_im_context_filter_keypress"); + if (GtkCheckVersion(4)) { + return DlCast(filter)( + context, reinterpret_cast(event)); + } + return DlCast(filter)(context, event); +} + +DISABLE_CFI_ICALL +bool GtkFileChooserSetCurrentFolder(GtkFileChooser* dialog, + const base::FilePath& path) { + static void* set = DlSym(GetLibGtk(), "gtk_file_chooser_set_current_folder"); + if (GtkCheckVersion(4)) { + auto file = TakeGObject(g_file_new_for_path(path.value().c_str())); + return DlCast(set)(dialog, file, + nullptr); + } + return DlCast(set)(dialog, + path.value().c_str()); +} + +DISABLE_CFI_ICALL +void GtkRenderIcon(GtkStyleContext* context, + cairo_t* cr, + GdkPixbuf* pixbuf, + GdkTexture* texture, + double x, + double y) { + static void* render = DlSym(GetLibGtk(), "gtk_render_icon"); + if (GtkCheckVersion(4)) { + DCHECK(texture); + DlCast( + render)(context, cr, texture, x, y); + } else { + DCHECK(pixbuf); + DlCast( + render)(context, cr, pixbuf, x, y); + } +} + +ScopedGObject Gtk4FileChooserGetFiles(GtkFileChooser* dialog) { + DCHECK(GtkCheckVersion(4)); + static void* get = DlSym(GetLibGtk(), "gtk_file_chooser_get_files"); + return TakeGObject(DlCast(get)(dialog)); +} + +void GtkStyleContextGet(GtkStyleContext* context, ...) { + va_list args; + va_start(args, context); + gtk_style_context_get_valist(context, gtk_style_context_get_state(context), + args); + va_end(args); +} + +void GtkStyleContextGetStyle(GtkStyleContext* context, ...) { + va_list args; + va_start(args, context); + gtk_style_context_get_style_valist(context, args); + va_end(args); +} + +DISABLE_CFI_ICALL +ScopedGObject Gtk3IconThemeLookupByGicon( + GtkIconTheme* theme, + GIcon* icon, + int size, + GtkIconLookupFlags flags) { + DCHECK(!GtkCheckVersion(4)); + static void* lookup = DlSym(GetLibGtk(), "gtk_icon_theme_lookup_by_gicon"); + return TakeGObject( + DlCast( + lookup)(theme, icon, size, flags)); +} + +DISABLE_CFI_ICALL +ScopedGObject Gtk4IconThemeLookupIcon( + GtkIconTheme* theme, + const char* icon_name, + const char* fallbacks[], + int size, + int scale, + GtkTextDirection direction, + GtkIconLookupFlags flags) { + static void* lookup = DlSym(GetLibGtk(), "gtk_icon_theme_lookup_icon"); + return TakeGObject( + DlCast( + lookup)(theme, icon_name, fallbacks, size, scale, direction, flags)); +} + +DISABLE_CFI_ICALL +ScopedGObject Gtk4IconThemeLookupByGicon( + GtkIconTheme* theme, + GIcon* icon, + int size, + int scale, + GtkTextDirection direction, + GtkIconLookupFlags flags) { + static void* lookup = DlSym(GetLibGtk(), "gtk_icon_theme_lookup_by_gicon"); + DCHECK(GtkCheckVersion(4)); + return TakeGObject( + DlCast(lookup)( + theme, icon, size, scale, direction, flags)); +} + +} // namespace gtk diff --git a/chromium/ui/gtk/gtk_compat.h b/chromium/ui/gtk/gtk_compat.h new file mode 100644 index 00000000000..5d87d1b14c3 --- /dev/null +++ b/chromium/ui/gtk/gtk_compat.h @@ -0,0 +1,99 @@ +// 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_COMPAT_H_ +#define UI_GTK_GTK_COMPAT_H_ + +#include +#include +#include +#include + +#include +#include + +#include "base/component_export.h" +#include "base/files/file_path.h" +#include "base/version.h" +#include "ui/base/glib/scoped_gobject.h" +#include "ui/gfx/geometry/insets.h" +#include "ui/gtk/gtk_types.h" + +extern "C" { +#include "ui/gtk/gdk.sigs" +#include "ui/gtk/gdk_pixbuf.sigs" +#include "ui/gtk/gio.sigs" +#include "ui/gtk/gsk.sigs" +#include "ui/gtk/gtk.sigs" +} + +namespace gtk { + +// Loads libgtk and related libraries and returns true on success. +COMPONENT_EXPORT(GTK) bool LoadGtk(int gtk_version); + +const base::Version& GtkVersion(); + +// Returns true iff the runtime version of Gtk used meets +// |major|.|minor|.|micro|. LoadGtk() must have been called +// prior to calling this function. +bool GtkCheckVersion(int major, int minor = 0, int micro = 0); + +// The below functions replace GTK functions whose interface has +// changed across versions, but whose (symbol) names have not. + +void GtkInit(const std::vector& args); + +gfx::Insets GtkStyleContextGetPadding(GtkStyleContext* context); + +gfx::Insets GtkStyleContextGetBorder(GtkStyleContext* context); + +gfx::Insets GtkStyleContextGetMargin(GtkStyleContext* context); + +bool GtkImContextFilterKeypress(GtkIMContext* context, GdkEventKey* event); + +bool GtkFileChooserSetCurrentFolder(GtkFileChooser* dialog, + const base::FilePath& path); + +void GtkRenderIcon(GtkStyleContext* context, + cairo_t* cr, + GdkPixbuf* pixbuf, + GdkTexture* texture, + double x, + double y); + +ScopedGObject Gtk4FileChooserGetFiles(GtkFileChooser* dialog); + +ScopedGObject Gtk3IconThemeLookupByGicon(GtkIconTheme* theme, + GIcon* icon, + int size, + GtkIconLookupFlags flags); + +ScopedGObject Gtk4IconThemeLookupByGicon( + GtkIconTheme* theme, + GIcon* icon, + int size, + int scale, + GtkTextDirection direction, + GtkIconLookupFlags flags); + +ScopedGObject Gtk4IconThemeLookupIcon( + GtkIconTheme* theme, + const char* icon_name, + const char* fallbacks[], + int size, + int scale, + GtkTextDirection direction, + GtkIconLookupFlags flags); + +// generate_stubs cannot forward to C-style variadic functions, so the +// functions below wrap the corresponding GTK va_list functions. + +void GtkStyleContextGet(GtkStyleContext* context, ...); + +void GtkStyleContextGetStyle(GtkStyleContext* context, ...); + +} // namespace gtk + +#endif diff --git a/chromium/ui/gtk/gtk_key_bindings_handler.cc b/chromium/ui/gtk/gtk_key_bindings_handler.cc index c663a207462..bacf6abb9f2 100644 --- a/chromium/ui/gtk/gtk_key_bindings_handler.cc +++ b/chromium/ui/gtk/gtk_key_bindings_handler.cc @@ -12,36 +12,21 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/strings/string_util.h" +#include "ui/base/glib/glib_cast.h" #include "ui/base/ime/text_edit_commands.h" #include "ui/events/event.h" +#include "ui/gtk/gtk_compat.h" #include "ui/gtk/gtk_util.h" using ui::TextEditCommand; -// TODO(erg): Rewrite the old gtk_key_bindings_handler_unittest.cc and get them -// in a state that links. This code was adapted from the content layer GTK -// code, which had some simple unit tests. However, the changes in the public -// interface basically meant the tests need to be rewritten; this imposes weird -// linking requirements regarding GTK+ as we don't have a gtk_unittests -// yet. http://crbug.com/358297. - -namespace { - -GtkWidget* CreateInvisibleWindow() { -#if GTK_CHECK_VERSION(3, 90, 0) - return gtk_invisible_new(); -#else - return gtk_offscreen_window_new(); -#endif -} - -} // namespace - namespace gtk { GtkKeyBindingsHandler::GtkKeyBindingsHandler() - : fake_window_(CreateInvisibleWindow()), handler_(CreateNewHandler()) { - gtk_container_add(GTK_CONTAINER(fake_window_), handler_); + : fake_window_(gtk_offscreen_window_new()), handler_(CreateNewHandler()) { + DCHECK(!GtkCheckVersion(4)); + gtk_container_add( + GlibCast(fake_window_, gtk_container_get_type()), handler_); } GtkKeyBindingsHandler::~GtkKeyBindingsHandler() { @@ -66,7 +51,9 @@ bool GtkKeyBindingsHandler::MatchEvent( // If this key event matches a predefined key binding, corresponding signal // will be emitted. - gtk_bindings_activate_event(G_OBJECT(handler_), &gdk_event->key); + auto* key = reinterpret_cast(gdk_event); + DCHECK(key->type == GDK_KEY_PRESS || key->type == GDK_KEY_RELEASE); + gtk_bindings_activate_event(G_OBJECT(handler_), key); gdk_event_free(gdk_event); bool matched = !edit_commands_.empty(); @@ -87,9 +74,7 @@ GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() { // Prevents it from handling any events by itself. gtk_widget_set_sensitive(GTK_WIDGET(handler), FALSE); -#if !GTK_CHECK_VERSION(3, 90, 0) gtk_widget_set_events(GTK_WIDGET(handler), 0); -#endif gtk_widget_set_can_focus(GTK_WIDGET(handler), TRUE); return GTK_WIDGET(handler); @@ -97,7 +82,7 @@ GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() { void GtkKeyBindingsHandler::EditCommandMatched(TextEditCommand command, const std::string& value) { - edit_commands_.push_back(ui::TextEditCommandAuraLinux(command, value)); + edit_commands_.emplace_back(command, value); } void GtkKeyBindingsHandler::HandlerInit(Handler* self) { @@ -117,10 +102,6 @@ void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass* klass) { text_view_class->paste_clipboard = PasteClipboard; text_view_class->set_anchor = SetAnchor; text_view_class->toggle_overwrite = ToggleOverwrite; -#if !GTK_CHECK_VERSION(3, 90, 0) - GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); - widget_class->show_help = ShowHelp; -#endif // "move-focus", "move-viewport", "select-all" and "toggle-cursor-visible" // have no corresponding virtual methods. Since glib 2.18 (gtk 2.14), @@ -138,6 +119,9 @@ void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass* klass) { g_signal_override_class_handler("toggle-cursor-visible", G_TYPE_FROM_CLASS(klass), G_CALLBACK(ToggleCursorVisible)); + + g_signal_override_class_handler("show-help", G_TYPE_FROM_CLASS(klass), + G_CALLBACK(ShowHelp)); } GType GtkKeyBindingsHandler::HandlerGetType() { @@ -231,9 +215,10 @@ void GtkKeyBindingsHandler::DeleteFromCursor(GtkTextView* text_view, if (count < 0) count = -count; for (; count > 0; --count) { - for (size_t i = 0; i < base::size(commands); ++i) - if (commands[i] != TextEditCommand::INVALID_COMMAND) - owner->EditCommandMatched(commands[i], std::string()); + for (auto& command : commands) { + if (command != TextEditCommand::INVALID_COMMAND) + owner->EditCommandMatched(command, std::string()); + } } } @@ -382,13 +367,11 @@ void GtkKeyBindingsHandler::ToggleOverwrite(GtkTextView* text_view) { // Not supported by Blink. } -#if !GTK_CHECK_VERSION(3, 90, 0) gboolean GtkKeyBindingsHandler::ShowHelp(GtkWidget* widget, GtkWidgetHelpType arg1) { // Just for disabling the default handler. - return FALSE; + return TRUE; } -#endif void GtkKeyBindingsHandler::MoveFocus(GtkWidget* widget, GtkDirectionType arg1) { diff --git a/chromium/ui/gtk/gtk_key_bindings_handler.h b/chromium/ui/gtk/gtk_key_bindings_handler.h index b996a553ae0..afd795a4471 100644 --- a/chromium/ui/gtk/gtk_key_bindings_handler.h +++ b/chromium/ui/gtk/gtk_key_bindings_handler.h @@ -12,6 +12,7 @@ #include "ui/base/ime/linux/text_edit_command_auralinux.h" #include "ui/events/platform_event.h" +#include "ui/gtk/gtk_types.h" namespace ui { class Event; @@ -122,10 +123,8 @@ class GtkKeyBindingsHandler { // Handler of "toggle-overwrite" signal. static void ToggleOverwrite(GtkTextView* text_view); -#if !GTK_CHECK_VERSION(3, 90, 0) // Handler of "show-help" signal. static gboolean ShowHelp(GtkWidget* widget, GtkWidgetHelpType arg1); -#endif // Handler of "move-focus" signal. static void MoveFocus(GtkWidget* widget, GtkDirectionType arg1); diff --git a/chromium/ui/gtk/gtk_types.h b/chromium/ui/gtk/gtk_types.h new file mode 100644 index 00000000000..a891983fdf0 --- /dev/null +++ b/chromium/ui/gtk/gtk_types.h @@ -0,0 +1,90 @@ +// 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_TYPES_H_ +#define UI_GTK_GTK_TYPES_H_ + +#include + +#include "ui/gtk/gtk_buildflags.h" + +// This file provides types that are only available in specific versions of GTK. + +extern "C" { +#if BUILDFLAG(GTK_VERSION) == 3 +using GskRenderNodeType = enum { + GSK_NOT_A_RENDER_NODE = 0, + GSK_CONTAINER_NODE, + GSK_CAIRO_NODE, + GSK_COLOR_NODE, + GSK_LINEAR_GRADIENT_NODE, + GSK_REPEATING_LINEAR_GRADIENT_NODE, + GSK_RADIAL_GRADIENT_NODE, + GSK_REPEATING_RADIAL_GRADIENT_NODE, + GSK_CONIC_GRADIENT_NODE, + GSK_BORDER_NODE, + GSK_TEXTURE_NODE, + GSK_INSET_SHADOW_NODE, + GSK_OUTSET_SHADOW_NODE, + GSK_TRANSFORM_NODE, + GSK_OPACITY_NODE, + GSK_COLOR_MATRIX_NODE, + GSK_REPEAT_NODE, + GSK_CLIP_NODE, + GSK_ROUNDED_CLIP_NODE, + GSK_SHADOW_NODE, + GSK_BLEND_NODE, + GSK_CROSS_FADE_NODE, + GSK_TEXT_NODE, + GSK_BLUR_NODE, + GSK_DEBUG_NODE, + GSK_GL_SHADER_NODE +}; + +enum GdkMemoryFormat : int; + +using GskRenderNode = struct _GskRenderNode; +using GtkIconPaintable = struct _GtkIconPaintable; +using GdkTexture = struct _GdkTexture; +using GdkSnapshot = struct _GdkSnapshot; +using GtkSnapshot = GdkSnapshot; +using GdkPaintable = struct _GdkPaintable; +using GtkNative = struct _GtkNative; +using GdkSurface = struct _GdkSurface; + +constexpr GdkMemoryFormat GDK_MEMORY_B8G8R8A8 = static_cast(3); +#else +enum GtkWidgetHelpType : int; + +using GtkWidgetPath = struct _GtkWidgetPath; +using GtkContainer = struct _GtkContainer; +using GdkEventKey = struct _GdkEventKey; +using GdkWindow = struct _GdkWindow; +using GdkKeymap = struct _GdkKeymap; +using GtkIconInfo = struct _GtkIconInfo; +using GdkScreen = struct _GdkScreen; + +struct _GdkEventKey { + GdkEventType type; + GdkWindow* window; + gint8 send_event; + guint32 time; + guint state; + guint keyval; + gint length; + gchar* string; + guint16 hardware_keycode; + guint8 group; + guint is_modifier : 1; +}; + +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"; +#endif +} + +#endif // UI_GTK_GTK_TYPES_H_ diff --git a/chromium/ui/gtk/gtk_ui.cc b/chromium/ui/gtk/gtk_ui.cc index 2c96ffb0b5b..b99afd66e79 100644 --- a/chromium/ui/gtk/gtk_ui.cc +++ b/chromium/ui/gtk/gtk_ui.cc @@ -31,6 +31,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkShader.h" #include "ui/base/cursor/cursor_theme_manager_observer.h" +#include "ui/base/glib/glib_cast.h" #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" @@ -46,7 +47,7 @@ #include "ui/gfx/image/image_skia_source.h" #include "ui/gfx/skbitmap_operations.h" #include "ui/gfx/skia_util.h" -#include "ui/gtk/gdk_pixbuf.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_util.h" @@ -130,7 +131,7 @@ class GtkButtonImageSource : public gfx::ImageSkiaSource { width, height, width * 4); cairo_t* cr = cairo_create(surface); - ScopedStyleContext context = GetStyleContextFromCss("GtkButton#button"); + GtkCssContext context = GetStyleContextFromCss("GtkButton#button"); GtkStateFlags state_flags = StateToStateFlags(state_); if (focus_) { state_flags = @@ -142,35 +143,25 @@ class GtkButtonImageSource : public gfx::ImageSkiaSource { if (focus_) { gfx::Rect focus_rect(width, height); -#if !GTK_CHECK_VERSION(3, 90, 0) if (!GtkCheckVersion(3, 14)) { gint focus_pad; - gtk_style_context_get_style(context, "focus-padding", &focus_pad, - nullptr); + GtkStyleContextGetStyle(context, "focus-padding", &focus_pad, nullptr); focus_rect.Inset(focus_pad, focus_pad); if (state_ == ui::NativeTheme::kPressed) { gint child_displacement_x, child_displacement_y; gboolean displace_focus; - gtk_style_context_get_style( - context, "child-displacement-x", &child_displacement_x, - "child-displacement-y", &child_displacement_y, "displace-focus", - &displace_focus, nullptr); + GtkStyleContextGetStyle(context, "child-displacement-x", + &child_displacement_x, "child-displacement-y", + &child_displacement_y, "displace-focus", + &displace_focus, nullptr); if (displace_focus) focus_rect.Offset(child_displacement_x, child_displacement_y); } } -#endif - if (!GtkCheckVersion(3, 20)) { - GtkBorder border; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_border(context, &border); -#else - gtk_style_context_get_border(context, state_flags, &border); -#endif - focus_rect.Inset(border.left, border.top, border.right, border.bottom); - } + if (!GtkCheckVersion(3, 20)) + focus_rect.Inset(GtkStyleContextGetBorder(context)); gtk_render_focus(context, cr, focus_rect.x(), focus_rect.y(), focus_rect.width(), focus_rect.height()); @@ -211,23 +202,6 @@ class GtkButtonPainter : public views::Painter { DISALLOW_COPY_AND_ASSIGN(GtkButtonPainter); }; -struct GObjectDeleter { - void operator()(void* ptr) { g_object_unref(ptr); } -}; -struct GtkIconInfoDeleter { - void operator()(GtkIconInfo* ptr) { -#if GTK_CHECK_VERSION(3, 90, 0) - g_object_unref(ptr); -#else - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - gtk_icon_info_free(ptr); - G_GNUC_END_IGNORE_DEPRECATIONS -#endif - } -}; -typedef std::unique_ptr ScopedGIcon; -typedef std::unique_ptr ScopedGtkIconInfo; - // Number of app indicators used (used as part of app-indicator id). int indicators_count; @@ -325,18 +299,18 @@ GtkUi::GtkUi(ui::GtkUiDelegate* delegate) : delegate_(delegate) { {ActionSource::kMiddleClick, GetDefaultMiddleClickAction()}, {ActionSource::kRightClick, Action::kMenu}}; + static bool loaded = LoadGtk(BUILDFLAG(GTK_VERSION)); + CHECK(loaded); + // Avoid GTK initializing atk-bridge, and let AuraLinux implementation // do it once it is ready. std::unique_ptr env(base::Environment::Create()); env->SetVar("NO_AT_BRIDGE", "1"); GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); native_theme_ = NativeThemeGtk::instance(); - fake_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_realize(fake_window_); } GtkUi::~GtkUi() { - gtk_widget_destroy(fake_window_); g_gtk_ui = nullptr; } @@ -359,9 +333,6 @@ void GtkUi::Initialize() { } #endif - CHECK(ui_gtk::InitializeStubs( - {{ui_gtk::kModuleGdk_pixbuf, {"libgdk_pixbuf-2.0.so.0"}}})); - GtkSettings* settings = gtk_settings_get_default(); g_signal_connect_after(settings, "notify::gtk-theme-name", G_CALLBACK(OnThemeChangedThunk), this); @@ -374,15 +345,19 @@ void GtkUi::Initialize() { g_signal_connect_after(settings, "notify::gtk-cursor-theme-size", G_CALLBACK(OnCursorThemeSizeChangedThunk), this); - GdkScreen* screen = gdk_screen_get_default(); // Listen for DPI changes. - g_signal_connect_after(screen, "notify::resolution", - G_CALLBACK(OnDeviceScaleFactorMaybeChangedThunk), - this); + auto* dpi_callback = G_CALLBACK(OnDeviceScaleFactorMaybeChangedThunk); + if (GtkCheckVersion(4)) { + g_signal_connect_after(settings, "notify::gtk-xft-dpi", dpi_callback, this); + } else { + GdkScreen* screen = gdk_screen_get_default(); + g_signal_connect_after(screen, "notify::resolution", dpi_callback, this); + } + // Listen for scale factor changes. We would prefer to listen on - // |screen|, but there is no scale-factor property, so use an + // a GdkScreen, but there is no scale-factor property, so use an // unmapped window instead. - g_signal_connect(fake_window_, "notify::scale-factor", + g_signal_connect(GetDummyWindow(), "notify::scale-factor", G_CALLBACK(OnDeviceScaleFactorMaybeChangedThunk), this); LoadGtkValues(); @@ -399,7 +374,7 @@ void GtkUi::Initialize() { indicators_count = 0; - GetDelegate()->OnInitialized(); + GetDelegate()->OnInitialized(GetDummyWindow()); } bool GtkUi::GetTint(int id, color_utils::HSL* tint) const { @@ -521,35 +496,56 @@ gfx::Image GtkUi::GetIconForContentType(const std::string& content_type, std::string content_types[] = {content_type, kUnknownContentType}; for (size_t i = 0; i < base::size(content_types); ++i) { - ScopedGIcon icon(g_content_type_get_icon(content_types[i].c_str())); - ScopedGtkIconInfo icon_info(gtk_icon_theme_lookup_by_gicon( - theme, icon.get(), size, - static_cast(GTK_ICON_LOOKUP_FORCE_SIZE))); - if (!icon_info) - continue; - auto* surface = - gtk_icon_info_load_surface(icon_info.get(), nullptr, nullptr); - if (!surface) - continue; - DCHECK_EQ(cairo_surface_get_type(surface), CAIRO_SURFACE_TYPE_IMAGE); - DCHECK_EQ(cairo_image_surface_get_format(surface), CAIRO_FORMAT_ARGB32); - + auto icon = TakeGObject(g_content_type_get_icon(content_type.c_str())); SkBitmap bitmap; - SkImageInfo image_info = - SkImageInfo::Make(cairo_image_surface_get_width(surface), - cairo_image_surface_get_height(surface), - kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); - if (!bitmap.installPixels( - image_info, cairo_image_surface_get_data(surface), - image_info.minRowBytes(), - [](void*, void* surface) { - cairo_surface_destroy( - reinterpret_cast(surface)); - }, - surface)) { - continue; + if (GtkCheckVersion(4)) { + auto icon_paintable = Gtk4IconThemeLookupByGicon( + theme, icon.get(), size, 1, GTK_TEXT_DIR_NONE, + static_cast(0)); + if (!icon_paintable) + continue; + + auto* paintable = GlibCast(icon_paintable.get(), + gdk_paintable_get_type()); + auto* snapshot = gtk_snapshot_new(); + gdk_paintable_snapshot(paintable, snapshot, size, size); + auto* node = gtk_snapshot_free_to_node(snapshot); + GdkTexture* texture = GetTextureFromRenderNode(node); + + bitmap.allocN32Pixels(gdk_texture_get_width(texture), + gdk_texture_get_height(texture)); + gdk_texture_download(texture, static_cast(bitmap.getAddr(0, 0)), + bitmap.rowBytes()); + + gsk_render_node_unref(node); + } else { + auto icon_info = Gtk3IconThemeLookupByGicon( + theme, icon.get(), size, + static_cast(GTK_ICON_LOOKUP_FORCE_SIZE)); + if (!icon_info) + continue; + auto* surface = + gtk_icon_info_load_surface(icon_info.get(), nullptr, nullptr); + if (!surface) + continue; + DCHECK_EQ(cairo_surface_get_type(surface), CAIRO_SURFACE_TYPE_IMAGE); + DCHECK_EQ(cairo_image_surface_get_format(surface), CAIRO_FORMAT_ARGB32); + + SkImageInfo image_info = + SkImageInfo::Make(cairo_image_surface_get_width(surface), + cairo_image_surface_get_height(surface), + kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); + if (!bitmap.installPixels( + image_info, cairo_image_surface_get_data(surface), + image_info.minRowBytes(), + [](void*, void* surface) { + cairo_surface_destroy( + reinterpret_cast(surface)); + }, + surface)) { + continue; + } } - gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); image_skia.MakeThreadSafe(); return gfx::Image(image_skia); @@ -572,7 +568,7 @@ std::unique_ptr GtkUi::CreateNativeBorder( static struct { bool focus; views::Button::ButtonState state; - } const paintstate[] = { + } const paintstates[] = { {!kFocus, views::Button::STATE_NORMAL}, {!kFocus, views::Button::STATE_HOVERED}, {!kFocus, views::Button::STATE_PRESSED}, @@ -583,12 +579,12 @@ std::unique_ptr GtkUi::CreateNativeBorder( {kFocus, views::Button::STATE_DISABLED}, }; - for (unsigned i = 0; i < base::size(paintstate); i++) { + for (const auto& paintstate : paintstates) { gtk_border->SetPainter( - paintstate[i].focus, paintstate[i].state, - border->PaintsButtonState(paintstate[i].focus, paintstate[i].state) - ? std::make_unique(paintstate[i].focus, - paintstate[i].state) + paintstate.focus, paintstate.state, + border->PaintsButtonState(paintstate.focus, paintstate.state) + ? std::make_unique(paintstate.focus, + paintstate.state) : nullptr); } @@ -663,7 +659,7 @@ views::LinuxUI::WindowFrameAction GtkUi::GetWindowFrameAction( void GtkUi::NotifyWindowManagerStartupComplete() { // TODO(port) Implement this using _NET_STARTUP_INFO_BEGIN/_NET_STARTUP_INFO // from http://standards.freedesktop.org/startup-notification-spec/ instead. - gdk_notify_startup_complete(); + gdk_display_notify_startup_complete(gdk_display_get_default(), nullptr); } void GtkUi::AddDeviceScaleFactorObserver( @@ -708,11 +704,14 @@ static struct { base::flat_map GtkUi::GetKeyboardLayoutMap() { GdkDisplay* display = gdk_display_get_default(); - GdkKeymap* keymap = gdk_keymap_get_for_display(display); - if (!keymap) - return {}; + GdkKeymap* keymap = nullptr; + if (!GtkCheckVersion(4)) { + keymap = gdk_keymap_get_for_display(display); + if (!keymap) + return {}; + } - ui::DomKeyboardLayoutManager* layouts = new ui::DomKeyboardLayoutManager(); + auto layouts = std::make_unique(); auto map = base::flat_map(); for (unsigned int i_domcode = 0; @@ -726,18 +725,21 @@ base::flat_map GtkUi::GetKeyboardLayoutMap() { // The order of the layouts is based on the system default ordering in // Keyboard Settings. The currently active layout does not affect this // order. - if (gdk_keymap_get_entries_for_keycode(keymap, keycode, &keys, &keyvals, - &n_entries)) { + const bool success = + GtkCheckVersion(4) ? gdk_display_map_keycode(display, keycode, &keys, + &keyvals, &n_entries) + : gdk_keymap_get_entries_for_keycode( + keymap, keycode, &keys, &keyvals, &n_entries); + if (success) { for (gint i = 0; i < n_entries; ++i) { // There are 4 entries per layout group, one each for shift level 0..3. // We only care about the unshifted values (level = 0). if (keys[i].level == 0) { uint16_t unicode = gdk_keyval_to_unicode(keyvals[i]); if (unicode == 0) { - for (unsigned int i_dead = 0; i_dead < base::size(kDeadKeyMapping); - ++i_dead) { - if (keyvals[i] == kDeadKeyMapping[i_dead].gdk_key) - unicode = kDeadKeyMapping[i_dead].unicode; + for (const auto& i_dead : kDeadKeyMapping) { + if (keyvals[i] == i_dead.gdk_key) + unicode = i_dead.unicode; } } if (unicode != 0) @@ -746,9 +748,7 @@ base::flat_map GtkUi::GetKeyboardLayoutMap() { } } g_free(keys); - keys = nullptr; g_free(keyvals); - keyvals = nullptr; } return layouts->GetFirstAsciiCapableLayout()->GetMap(); } @@ -774,6 +774,10 @@ int GtkUi::GetCursorThemeSize() { bool GtkUi::MatchEvent(const ui::Event& event, std::vector* commands) { + // GTK4 dropped custom key bindings. + if (GtkCheckVersion(4)) + return false; + // TODO(crbug.com/963419): Use delegate's |GetGdkKeymap| here to // determine if GtkUi's key binding handling implementation is used or not. // Ozone/Wayland was unintentionally using GtkUi for keybinding handling, so @@ -794,7 +798,7 @@ void GtkUi::OnThemeChanged(GtkSettings* settings, GtkParamSpec* param) { native_frame_colors_.clear(); native_theme_->OnThemeChanged(settings, param); LoadGtkValues(); - native_theme_->NotifyObservers(); + native_theme_->NotifyOnNativeThemeUpdated(); } void GtkUi::OnCursorThemeNameChanged(GtkSettings* settings, @@ -856,7 +860,7 @@ void GtkUi::UpdateColors() { colors_[ThemeProperties::COLOR_NTP_HEADER] = GetBorderColor("GtkButton#button"); - SkColor tab_text_color = GetFgColor("GtkLabel"); + SkColor tab_text_color = GetFgColor("GtkLabel#label"); colors_[ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON] = tab_text_color; colors_[ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON_HOVERED] = tab_text_color; colors_[ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON_PRESSED] = tab_text_color; @@ -921,9 +925,9 @@ void GtkUi::UpdateColors() { tab_color; const SkColor background_tab_text_color = - GetFgColor(header_selector + " GtkLabel.title"); + GetFgColor(header_selector + " GtkLabel#label.title"); const SkColor background_tab_text_color_inactive = - GetFgColor(header_selector_inactive + " GtkLabel.title"); + GetFgColor(header_selector_inactive + " GtkLabel#label.title"); color_map[ThemeProperties::COLOR_TAB_FOREGROUND_INACTIVE_FRAME_ACTIVE] = background_tab_text_color; @@ -986,8 +990,7 @@ void GtkUi::UpdateColors() { void GtkUi::UpdateDefaultFont() { gfx::SetFontRenderParamsDeviceScaleFactor(device_scale_factor_); - GtkWidget* fake_label = gtk_label_new(nullptr); - g_object_ref_sink(fake_label); // Remove the floating reference. + auto fake_label = TakeGObject(gtk_label_new(nullptr)); PangoContext* pc = gtk_widget_get_pango_context(fake_label); const PangoFontDescription* desc = pango_context_get_font_description(pc); @@ -1024,20 +1027,25 @@ void GtkUi::UpdateDefaultFont() { default_font_render_params_ = gfx::GetFontRenderParams(query, &default_font_family_); default_font_style_ = query.style; - - gtk_widget_destroy(fake_label); - g_object_unref(fake_label); } float GtkUi::GetRawDeviceScaleFactor() { if (display::Display::HasForceDeviceScaleFactor()) return display::Display::GetForcedDeviceScaleFactor(); - GdkScreen* screen = gdk_screen_get_default(); - float scale = gtk_widget_get_scale_factor(fake_window_); + float scale = gtk_widget_get_scale_factor(GetDummyWindow()); DCHECK_GT(scale, 0.0); - gdouble resolution = gdk_screen_get_resolution(screen); + double resolution = 0; + if (GtkCheckVersion(4)) { + auto* settings = gtk_settings_get_default(); + int dpi = 0; + g_object_get(settings, "gtk-xft-dpi", &dpi, nullptr); + resolution = dpi / 1024.0; + } else { + GdkScreen* screen = gdk_screen_get_default(); + resolution = gdk_screen_get_resolution(screen); + } if (resolution > 0) scale *= resolution / kDefaultDPI; diff --git a/chromium/ui/gtk/gtk_ui.h b/chromium/ui/gtk/gtk_ui.h index 84032b30271..3cb1c8df374 100644 --- a/chromium/ui/gtk/gtk_ui.h +++ b/chromium/ui/gtk/gtk_ui.h @@ -13,7 +13,6 @@ #include "base/component_export.h" #include "base/macros.h" #include "base/observer_list.h" -#include "build/buildflag.h" #include "ui/base/glib/glib_signal.h" #include "ui/gfx/color_utils.h" #include "ui/gtk/gtk_ui_delegate.h" @@ -24,13 +23,12 @@ typedef struct _GParamSpec GParamSpec; typedef struct _GtkParamSpec GtkParamSpec; typedef struct _GtkSettings GtkSettings; typedef struct _GtkStyle GtkStyle; -typedef struct _GtkWidget GtkWidget; namespace gtk { using ColorMap = std::map; -class GtkKeyBindingsHandler; class DeviceScaleFactorObserver; +class GtkKeyBindingsHandler; class NativeThemeGtk; class SettingsProvider; @@ -153,9 +151,6 @@ class GtkUi : public views::LinuxUI { NativeThemeGtk* native_theme_; - // A regular GtkWindow. - GtkWidget* fake_window_; - // Colors calculated by LoadGtkValues() that are given to the // caller while |use_gtk_| is true. ColorMap colors_; @@ -192,6 +187,7 @@ class GtkUi : public views::LinuxUI { std::vector leading_buttons_; std::vector trailing_buttons_; + // This is only used on GTK3. std::unique_ptr key_bindings_handler_; // Objects to notify when the window frame button order changes. diff --git a/chromium/ui/gtk/gtk_ui_delegate.h b/chromium/ui/gtk/gtk_ui_delegate.h index 7e7c37b0a99..07a50008199 100644 --- a/chromium/ui/gtk/gtk_ui_delegate.h +++ b/chromium/ui/gtk/gtk_ui_delegate.h @@ -11,12 +11,8 @@ using GdkKeymap = struct _GdkKeymap; using GtkWindow = struct _GtkWindow; - -#if BUILDFLAG(GTK_VERSION) == 3 +using GtkWidget = struct _GtkWidget; using GdkWindow = struct _GdkWindow; -#else -using GdkWindow = struct _GdkSurface; -#endif namespace ui { @@ -40,8 +36,9 @@ class COMPONENT_EXPORT(GTK) GtkUiDelegate { // Returns the current active instance. static GtkUiDelegate* instance(); - // Called when the GtkUi instance initialization process finished. - virtual void OnInitialized() = 0; + // Called when the GtkUi instance initialization process finished. |widget| is + // a dummy window passed in for context. + virtual void OnInitialized(GtkWidget* widget) = 0; // Gets the GdkKeymap instance, which is used to translate KeyEvents into // GdkEvents before filtering them through GtkIM API. @@ -54,7 +51,7 @@ class COMPONENT_EXPORT(GTK) GtkUiDelegate { // Gtk dialog windows must be set transient for the browser window. This // function abstracts away such functionality. - virtual bool SetGdkWindowTransientFor(GdkWindow* window, + virtual bool SetGtkWidgetTransientFor(GtkWidget* widget, gfx::AcceleratedWidget parent) = 0; virtual void ClearTransientFor(gfx::AcceleratedWidget parent) = 0; diff --git a/chromium/ui/gtk/gtk_util.cc b/chromium/ui/gtk/gtk_util.cc index c3ae090b639..2bf77787479 100644 --- a/chromium/ui/gtk/gtk_util.cc +++ b/chromium/ui/gtk/gtk_util.cc @@ -4,7 +4,6 @@ #include "ui/gtk/gtk_util.h" -#include #include #include #include @@ -14,8 +13,8 @@ #include "base/command_line.h" #include "base/compiler_specific.h" -#include "base/debug/leak_annotations.h" #include "base/environment.h" +#include "base/strings/strcat.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" @@ -24,98 +23,155 @@ #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" #include "ui/gtk/gtk_ui.h" #include "ui/gtk/gtk_ui_delegate.h" +#include "ui/native_theme/common_theme.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/views/linux_ui/linux_ui.h" -WEAK_GTK_FN(gtk_widget_path_iter_set_object_name); -WEAK_GTK_FN(gtk_widget_path_iter_set_state); +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"; +GtkCssContext GetTooltipContext() { + return AppendCssNodeToStyleContext( + {}, GtkCheckVersion(3, 20) ? "#tooltip.background" + : "GtkWindow#window.background.tooltip"); +} + void CommonInitFromCommandLine(const base::CommandLine& command_line) { // Callers should have already called setlocale(LC_ALL, "") and // setlocale(LC_NUMERIC, "C") by now. Chrome does this in // service_manager::Main. DCHECK_EQ(strcmp(setlocale(LC_NUMERIC, nullptr), "C"), 0); - // This prevent GTK from calling setlocale(LC_ALL, ""), which potentially + // This prevents GTK from calling setlocale(LC_ALL, ""), which potentially // overwrites the LC_NUMERIC locale to something other than "C". gtk_disable_setlocale(); -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_init(); -#else - const std::vector& args = command_line.argv(); - int argc = args.size(); - std::unique_ptr argv(new char*[argc + 1]); - for (size_t i = 0; i < args.size(); ++i) { - // TODO(piman@google.com): can gtk_init modify argv? Just being safe - // here. - argv[i] = strdup(args[i].c_str()); - } - argv[argc] = nullptr; - char** argv_pointer = argv.get(); - - { - // http://crbug.com/423873 - ANNOTATE_SCOPED_MEMORY_LEAK; - gtk_init(&argc, &argv_pointer); - } - for (size_t i = 0; i < args.size(); ++i) { - free(argv[i]); - } -#endif + GtkInit(command_line.argv()); } -GdkModifierType GetIbusFlags(const ui::KeyEvent& key_event) { +GdkModifierType GetImeFlags(const ui::KeyEvent& key_event) { auto* properties = key_event.properties(); if (!properties) return static_cast(0); - auto it = properties->find(ui::kPropertyKeyboardIBusFlag); + auto it = properties->find(ui::kPropertyKeyboardImeFlag); DCHECK(it == properties->end() || it->second.size() == 1); uint8_t flags = (it != properties->end()) ? it->second[0] : 0; return static_cast(flags - << ui::kPropertyKeyboardIBusFlagOffset); + << ui::kPropertyKeyboardImeFlagOffset); } -GdkModifierType GetGdkKeyEventState(ui::KeyEvent key_event) { - // ui::KeyEvent uses a normalized modifier state which is not respected by - // Gtk, so we need to get the state from the display backend. Gtk instead - // follows the X11 spec in which the state of a key event is expected to be - // the mask of modifier keys _prior_ to this event. Some IMEs rely on this - // behavior. See https://crbug.com/1086946#c11. +GtkCssContext AppendCssNodeToStyleContextImpl( + GtkCssContext context, + GType gtype, + const std::string& name, + const std::string& object_name, + const std::vector& classes, + GtkStateFlags state, + float scale) { + if (GtkCheckVersion(4)) { + // GTK_TYPE_BOX is used instead of GTK_TYPE_WIDGET because: + // 1. Widgets are abstract and cannot be created directly. + // 2. The widget must be a container type so that it unrefs child widgets + // on destruction. + auto* widget_object = object_name.empty() + ? g_object_new(GTK_TYPE_BOX, nullptr) + : g_object_new(GTK_TYPE_BOX, "css-name", + object_name.c_str(), nullptr); + auto widget = TakeGObject(GTK_WIDGET(widget_object)); + + if (!name.empty()) + gtk_widget_set_name(widget, name.c_str()); + + std::vector css_classes; + css_classes.reserve(classes.size() + 1); + for (const auto& css_class : classes) + css_classes.push_back(css_class.c_str()); + css_classes.push_back(nullptr); + gtk_widget_set_css_classes(widget, css_classes.data()); + + gtk_widget_set_state_flags(widget, state, false); + + if (context) + gtk_widget_set_parent(widget, context.widget()); + + gtk_style_context_set_scale(gtk_widget_get_style_context(widget), scale); + + return GtkCssContext(widget, context ? context.root() : widget); + } else { + GtkWidgetPath* path = + context ? gtk_widget_path_copy(gtk_style_context_get_path(context)) + : gtk_widget_path_new(); + gtk_widget_path_append_type(path, gtype); + + if (!object_name.empty()) { + if (GtkCheckVersion(3, 20)) + gtk_widget_path_iter_set_object_name(path, -1, object_name.c_str()); + else + gtk_widget_path_iter_add_class(path, -1, object_name.c_str()); + } - GdkModifierType state = GetIbusFlags(key_event); - if (key_event.key_code() != ui::VKEY_PROCESSKEY) { - // This is an synthetized event when |key_code| is VKEY_PROCESSKEY. - // In such a case there is no event being dispatching in the display - // backend. - state = static_cast( - state | ui::GtkUiDelegate::instance()->GetGdkKeyState()); - } + if (!name.empty()) + gtk_widget_path_iter_set_name(path, -1, name.c_str()); - return state; + for (const auto& css_class : classes) + gtk_widget_path_iter_add_class(path, -1, css_class.c_str()); + + if (GtkCheckVersion(3, 14)) + gtk_widget_path_iter_set_state(path, -1, state); + + GtkCssContext child_context(TakeGObject(gtk_style_context_new())); + gtk_style_context_set_path(child_context, path); + if (GtkCheckVersion(3, 14)) { + gtk_style_context_set_state(child_context, state); + } else { + GtkStateFlags child_state = state; + if (context) { + child_state = static_cast( + child_state | gtk_style_context_get_state(context)); + } + gtk_style_context_set_state(child_context, child_state); + } + + gtk_style_context_set_scale(child_context, scale); + + gtk_style_context_set_parent(child_context, context); + + gtk_widget_path_unref(path); + return GtkCssContext(child_context); + } } -int GetKeyEventProperty(const ui::KeyEvent& key_event, - const char* property_key) { - auto* properties = key_event.properties(); - if (!properties) - return 0; - auto it = properties->find(property_key); - DCHECK(it == properties->end() || it->second.size() == 1); - return (it != properties->end()) ? it->second[0] : 0; +GtkWidget* CreateDummyWindow() { +#if BUILDFLAG(GTK_VERSION) >= 4 + GtkWidget* window = gtk_window_new(); +#else + GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); +#endif + gtk_widget_realize(window); + return window; } } // namespace -namespace gtk { - void GtkInitFromCommandLine(const base::CommandLine& command_line) { CommonInitFromCommandLine(command_line); } @@ -125,9 +181,8 @@ void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent) { return; gtk_widget_realize(dialog); - GdkWindow* gdk_window = gtk_widget_get_window(dialog); gfx::AcceleratedWidget parent_id = parent->GetHost()->GetAcceleratedWidget(); - GtkUi::GetDelegate()->SetGdkWindowTransientFor(gdk_window, parent_id); + GtkUi::GetDelegate()->SetGtkWidgetTransientFor(dialog, parent_id); // We also set the |parent| as a property of |dialog|, so that we can unlink // the two later. @@ -173,15 +228,6 @@ void ParseButtonLayout(const std::string& button_string, } } -namespace { - -float GetDeviceScaleFactor() { - views::LinuxUI* linux_ui = views::LinuxUI::instance(); - return linux_ui ? linux_ui->GetDeviceScaleFactor() : 1; -} - -} // namespace - CairoSurface::CairoSurface(SkBitmap& bitmap) : surface_(cairo_image_surface_create_for_data( static_cast(bitmap.getAddr(0, 0)), @@ -233,11 +279,45 @@ SkColor CairoSurface::GetAveragePixelValue(bool frame) { g * 255 / a, b * 255 / a); } -bool GtkCheckVersion(int major, int minor, int micro) { - static auto version = - std::make_tuple(gtk_get_major_version(), gtk_get_minor_version(), - gtk_get_micro_version()); - return version >= std::make_tuple(major, minor, micro); +GtkCssContext::GtkCssContext(GtkWidget* widget, GtkWidget* root) + : widget_(widget), root_(WrapGObject(root)) { + DCHECK(GtkCheckVersion(4)); +} + +GtkCssContext::GtkCssContext(GtkStyleContext* context) + : context_(WrapGObject(context)) { + DCHECK(!GtkCheckVersion(4)); +} + +GtkCssContext::GtkCssContext() = default; +GtkCssContext::GtkCssContext(const GtkCssContext&) = default; +GtkCssContext::GtkCssContext(GtkCssContext&&) = default; +GtkCssContext& GtkCssContext::operator=(const GtkCssContext&) = default; +GtkCssContext& GtkCssContext::operator=(GtkCssContext&&) = default; +GtkCssContext::~GtkCssContext() = default; + +GtkCssContext::operator GtkStyleContext*() { + if (GtkCheckVersion(4)) + return widget_ ? gtk_widget_get_style_context(widget_) : nullptr; + return context_; +} + +GtkCssContext GtkCssContext::GetParent() { + if (GtkCheckVersion(4)) { + return GtkCssContext(WrapGObject(gtk_widget_get_parent(widget_)), + root_ == widget_ ? ScopedGObject() : root_); + } + return GtkCssContext(WrapGObject(gtk_style_context_get_parent(context_))); +} + +GtkWidget* GtkCssContext::widget() { + DCHECK(GtkCheckVersion(4)); + return widget_; +} + +GtkWidget* GtkCssContext::root() { + DCHECK(GtkCheckVersion(4)); + return root_; } GtkStateFlags StateToStateFlags(ui::NativeTheme::State state) { @@ -263,12 +343,8 @@ SkColor GdkRgbaToSkColor(const GdkRGBA& color) { } NO_SANITIZE("cfi-icall") -ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context, - const std::string& css_node) { - GtkWidgetPath* path = - context ? gtk_widget_path_copy(gtk_style_context_get_path(context)) - : gtk_widget_path_new(); - +GtkCssContext AppendCssNodeToStyleContext(GtkCssContext context, + const std::string& css_node) { enum { CSS_TYPE, CSS_NAME, @@ -277,6 +353,7 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context, CSS_PSEUDOCLASS, CSS_NONE, } part_type = CSS_TYPE; + static const struct { const char* name; GtkStateFlags state_flag; @@ -292,15 +369,17 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context, {"visited", GTK_STATE_FLAG_VISITED}, {"checked", GTK_STATE_FLAG_CHECKED}, }; + + GType gtype = G_TYPE_NONE; + std::string name; + std::string object_name; + std::vector classes; GtkStateFlags state = GTK_STATE_FLAG_NORMAL; + base::StringTokenizer t(css_node, ".:#()"); t.set_options(base::StringTokenizer::RETURN_DELIMS); while (t.GetNext()) { if (t.token_is_delim()) { - if (t.token_begin() == css_node.begin()) { - // Special case for the first token. - gtk_widget_path_append_type(path, G_TYPE_NONE); - } switch (*t.token_begin()) { case '(': part_type = CSS_NAME; @@ -323,28 +402,20 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context, } else { switch (part_type) { case CSS_NAME: - gtk_widget_path_iter_set_name(path, -1, t.token().c_str()); + name = t.token(); break; case CSS_OBJECT_NAME: - if (GtkCheckVersion(3, 20)) { - DCHECK(gtk_widget_path_iter_set_object_name); - gtk_widget_path_iter_set_object_name(path, -1, t.token().c_str()); - } else { - gtk_widget_path_iter_add_class(path, -1, t.token().c_str()); - } + object_name = t.token(); break; case CSS_TYPE: { - GType type = g_type_from_name(t.token().c_str()); - DCHECK(type); - gtk_widget_path_append_type(path, type); - if (GtkCheckVersion(3, 20) && t.token() == "GtkLabel") { - DCHECK(gtk_widget_path_iter_set_object_name); - gtk_widget_path_iter_set_object_name(path, -1, "label"); - } +#if BUILDFLAG(GTK_VERSION) < 4 + gtype = g_type_from_name(t.token().c_str()); + DCHECK(gtype); +#endif break; } case CSS_CLASS: - gtk_widget_path_iter_add_class(path, -1, t.token().c_str()); + classes.push_back(t.token()); break; case CSS_PSEUDOCLASS: { GtkStateFlags state_flag = GTK_STATE_FLAG_NORMAL; @@ -365,36 +436,18 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context, // Always add a "chromium" class so that themes can style chromium // widgets specially if they want to. - gtk_widget_path_iter_add_class(path, -1, "chromium"); + classes.push_back("chromium"); - if (GtkCheckVersion(3, 14)) { - DCHECK(gtk_widget_path_iter_set_state); - gtk_widget_path_iter_set_state(path, -1, state); - } + float scale = std::round(GetDeviceScaleFactor()); - ScopedStyleContext child_context(gtk_style_context_new()); - gtk_style_context_set_path(child_context, path); - if (GtkCheckVersion(3, 14)) { - gtk_style_context_set_state(child_context, state); - } else { - GtkStateFlags child_state = state; - if (context) { - child_state = static_cast( - child_state | gtk_style_context_get_state(context)); - } - gtk_style_context_set_state(child_context, child_state); - } - gtk_style_context_set_scale(child_context, std::ceil(GetDeviceScaleFactor())); - gtk_style_context_set_parent(child_context, context); - gtk_widget_path_unref(path); - return child_context; + return AppendCssNodeToStyleContextImpl(context, gtype, name, object_name, + classes, state, scale); } -ScopedStyleContext GetStyleContextFromCss(const std::string& css_selector) { +GtkCssContext GetStyleContextFromCss(const std::string& css_selector) { // Prepend a window node to the selector since all widgets must live // in a window, but we don't want to specify that every time. - auto context = - AppendCssNodeToStyleContext(nullptr, "GtkWindow#window.background"); + auto context = AppendCssNodeToStyleContext({}, "GtkWindow#window.background"); for (const auto& widget_type : base::SplitString(css_selector, base::kWhitespaceASCII, @@ -406,7 +459,7 @@ ScopedStyleContext GetStyleContextFromCss(const std::string& css_selector) { SkColor GetFgColorFromStyleContext(GtkStyleContext* context) { GdkRGBA color; -#if GTK_CHECK_VERSION(3, 90, 0) +#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), @@ -415,7 +468,7 @@ SkColor GetFgColorFromStyleContext(GtkStyleContext* context) { return GdkRgbaToSkColor(color); } -SkColor GetBgColorFromStyleContext(GtkStyleContext* context) { +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 // cannot use the background-color here because some themes leave it @@ -439,37 +492,37 @@ SkColor GetFgColor(const std::string& css_selector) { } ScopedCssProvider GetCssProvider(const std::string& css) { - GtkCssProvider* provider = gtk_css_provider_new(); -#if GTK_CHECK_VERSION(3, 90, 0) + 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 - return ScopedCssProvider(provider); + return provider; } -void ApplyCssProviderToContext(GtkStyleContext* context, +void ApplyCssProviderToContext(GtkCssContext context, GtkCssProvider* provider) { while (context) { gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), G_MAXUINT); - context = gtk_style_context_get_parent(context); + context = context.GetParent(); } } -void ApplyCssToContext(GtkStyleContext* context, const std::string& css) { +void ApplyCssToContext(GtkCssContext context, const std::string& css) { auto provider = GetCssProvider(css); ApplyCssProviderToContext(context, provider); } void RenderBackground(const gfx::Size& size, cairo_t* cr, - GtkStyleContext* context) { + GtkCssContext context) { if (!context) return; - RenderBackground(size, cr, gtk_style_context_get_parent(context)); + RenderBackground(size, cr, context.GetParent()); gtk_render_background(context, cr, 0, 0, size.width(), size.height()); } @@ -491,23 +544,28 @@ 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; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_background_color(context, &selection_color); -#else gtk_style_context_get_background_color( context, gtk_style_context_get_state(context), &selection_color); -#endif G_GNUC_END_IGNORE_DEPRECATIONS; return GdkRgbaToSkColor(selection_color); +#else + NOTREACHED(); + return gfx::kPlaceholderColor; +#endif } -bool ContextHasClass(GtkStyleContext* context, const std::string& style_class) { +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 } SkColor GetSeparatorColor(const std::string& css_selector) { @@ -515,10 +573,14 @@ SkColor GetSeparatorColor(const std::string& css_selector) { return GetFgColor(css_selector); auto context = GetStyleContextFromCss(css_selector); + bool horizontal = ContextHasClass(context, "horizontal"); + int w = 1, h = 1; GtkBorder border, padding; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get(context, "min-width", &w, "min-height", &h, nullptr); +#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 @@ -531,7 +593,6 @@ SkColor GetSeparatorColor(const std::string& css_selector) { w += border.left + padding.left + padding.right + border.right; h += border.top + padding.top + padding.bottom + border.bottom; - bool horizontal = ContextHasClass(context, "horizontal"); if (horizontal) { w = 24; h = std::max(h, 1); @@ -562,7 +623,37 @@ int BuildXkbStateFromGdkEvent(unsigned int state, unsigned char group) { return state | ((group & 0x3) << 13); } +int GetKeyEventProperty(const ui::KeyEvent& key_event, + const char* property_key) { + auto* properties = key_event.properties(); + if (!properties) + return 0; + auto it = properties->find(property_key); + DCHECK(it == properties->end() || it->second.size() == 1); + return (it != properties->end()) ? it->second[0] : 0; +} + +GdkModifierType GetGdkKeyEventState(const ui::KeyEvent& key_event) { + // ui::KeyEvent uses a normalized modifier state which is not respected by + // Gtk, so we need to get the state from the display backend. Gtk instead + // follows the X11 spec in which the state of a key event is expected to be + // the mask of modifier keys _prior_ to this event. Some IMEs rely on this + // behavior. See https://crbug.com/1086946#c11. + + GdkModifierType state = GetImeFlags(key_event); + if (key_event.key_code() != ui::VKEY_PROCESSKEY) { + // This is an synthetized event when |key_code| is VKEY_PROCESSKEY. + // In such a case there is no event being dispatching in the display + // backend. + state = static_cast( + state | ui::GtkUiDelegate::instance()->GetGdkKeyState()); + } + + return state; +} + 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; auto event_time = key_event.time_stamp() - base::TimeTicks(); @@ -583,26 +674,448 @@ GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event) { // Build GdkEvent GdkEvent* gdk_event = gdk_event_new(event_type); - gdk_event->type = event_type; - gdk_event->key.time = event_time.InMilliseconds(); - gdk_event->key.hardware_keycode = hw_code; - gdk_event->key.keyval = keyval; - gdk_event->key.state = BuildXkbStateFromGdkEvent(state, group); - gdk_event->key.group = group; - gdk_event->key.send_event = key_event.flags() & ui::EF_FINAL; - gdk_event->key.is_modifier = state & GDK_MODIFIER_MASK; - gdk_event->key.length = 0; - gdk_event->key.string = nullptr; + GdkEventKey* gdk_event_key = reinterpret_cast(gdk_event); + gdk_event_key->type = event_type; + gdk_event_key->time = event_time.InMilliseconds(); + gdk_event_key->hardware_keycode = hw_code; + gdk_event_key->keyval = keyval; + gdk_event_key->state = BuildXkbStateFromGdkEvent(state, group); + gdk_event_key->group = group; + gdk_event_key->send_event = key_event.flags() & ui::EF_FINAL; + gdk_event_key->is_modifier = state & GDK_MODIFIER_MASK; + gdk_event_key->length = 0; + gdk_event_key->string = nullptr; return gdk_event; } GtkIconTheme* GetDefaultIconTheme() { -#if GTK_CHECK_VERSION(3, 90, 0) +#if BUILDFLAG(GTK_VERSION) >= 4 return gtk_icon_theme_get_for_display(gdk_display_get_default()); #else return gtk_icon_theme_get_default(); #endif } +void GtkWindowDestroy(GtkWidget* widget) { +#if BUILDFLAG(GTK_VERSION) >= 4 + gtk_window_destroy(GTK_WINDOW(widget)); +#else + gtk_widget_destroy(widget); +#endif +} + +GtkWidget* GetDummyWindow() { + static GtkWidget* window = CreateDummyWindow(); + return window; +} + +gfx::Size GetSeparatorSize(bool horizontal) { + auto widget = TakeGObject(gtk_separator_new( + horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL)); + GtkRequisition natural_size; + gtk_widget_get_preferred_size(widget, nullptr, &natural_size); + return {natural_size.width, natural_size.height}; +} + +float GetDeviceScaleFactor() { + views::LinuxUI* linux_ui = views::LinuxUI::instance(); + return linux_ui ? linux_ui->GetDeviceScaleFactor() : 1; +} + +GdkTexture* GetTextureFromRenderNode(GskRenderNode* node) { + DCHECK(GtkCheckVersion(4)); + struct { + GskRenderNodeType node_type; + GskRenderNode* (*get_child)(GskRenderNode*); + } constexpr simple_getters[] = { + {GSK_TRANSFORM_NODE, gsk_transform_node_get_child}, + {GSK_OPACITY_NODE, gsk_opacity_node_get_child}, + {GSK_COLOR_MATRIX_NODE, gsk_color_matrix_node_get_child}, + {GSK_REPEAT_NODE, gsk_repeat_node_get_child}, + {GSK_CLIP_NODE, gsk_clip_node_get_child}, + {GSK_ROUNDED_CLIP_NODE, gsk_rounded_clip_node_get_child}, + {GSK_SHADOW_NODE, gsk_shadow_node_get_child}, + {GSK_BLUR_NODE, gsk_blur_node_get_child}, + {GSK_DEBUG_NODE, gsk_debug_node_get_child}, + }; + struct { + GskRenderNodeType node_type; + guint (*get_n_children)(GskRenderNode*); + GskRenderNode* (*get_child)(GskRenderNode*, guint); + } constexpr container_getters[] = { + {GSK_CONTAINER_NODE, gsk_container_node_get_n_children, + gsk_container_node_get_child}, + {GSK_GL_SHADER_NODE, gsk_gl_shader_node_get_n_children, + gsk_gl_shader_node_get_child}, + }; + + if (!node) + return nullptr; + + auto node_type = gsk_render_node_get_node_type(node); + if (node_type == GSK_TEXTURE_NODE) + return gsk_texture_node_get_texture(node); + for (const auto& getter : simple_getters) { + if (node_type == getter.node_type) { + if (auto* texture = GetTextureFromRenderNode(getter.get_child(node))) + return texture; + } + } + for (const auto& getter : container_getters) { + if (node_type != getter.node_type) + continue; + for (guint i = 0; i < getter.get_n_children(node); ++i) { + if (auto* texture = GetTextureFromRenderNode(getter.get_child(node, i))) + return texture; + } + return nullptr; + } + return nullptr; +} + +// TODO(tluk): Refactor this to make better use of the hierarchical nature of +// ColorPipeline. +base::Optional SkColorFromColorId(ui::ColorId color_id) { + switch (color_id) { + case ui::kColorWindowBackground: + case ui::kColorDialogBackground: + case ui::kColorBubbleBackground: + case ui::kColorNotificationBackgroundInactive: + return GetBgColor(""); + case ui::kColorDialogForeground: + case ui::kColorAvatarIconIncognito: + return GetFgColor("GtkLabel#label"); + case ui::kColorBubbleFooterBackground: + case ui::kColorNotificationActionsBackground: + case ui::kColorNotificationBackgroundActive: + case ui::kColorNotificationImageBackground: + case ui::kColorSyncInfoBackground: + return GetBgColor("#statusbar"); + + // FocusableBorder + case ui::kColorFocusableBorderFocused: + // GetBorderColor("GtkEntry#entry:focus") is correct here. The focus ring + // around widgets is usually a lighter version of the "canonical theme + // color" - orange on Ambiance, blue on Adwaita, etc. However, Chrome + // lightens the color we give it, so it would look wrong if we give it an + // already-lightened color. This workaround returns the theme color + // directly, taken from a selected table row. This has matched the theme + // color on every theme that I've tested. + return GetBgColor( + "GtkTreeView#treeview.view " + "GtkTreeView#treeview.view.cell:selected:focus"); + case ui::kColorFocusableBorderUnfocused: + return GetBorderColor("GtkEntry#entry"); + + // Menu + case ui::kColorMenuBackground: + case ui::kColorMenuItemBackgroundHighlighted: + case ui::kColorMenuItemBackgroundAlertedInitial: + case ui::kColorMenuItemBackgroundAlertedTarget: + case ui::kColorSubtleEmphasisBackground: + return GetBgColor(kGtkCSSMenu); + case ui::kColorMenuBorder: + return GetBorderColor(kGtkCSSMenu); + case ui::kColorMenuItemBackgroundSelected: + return GetBgColor(StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ":hover"})); + case ui::kColorMenuItemForeground: + case ui::kColorMenuDropmarker: + case ui::kColorMenuItemForegroundHighlighted: + return GetFgColor( + StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, " GtkLabel#label"})); + case ui::kColorMenuItemForegroundSelected: + return GetFgColor( + StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ":hover GtkLabel#label"})); + case ui::kColorMenuItemForegroundDisabled: + return GetFgColor(StrCat( + {kGtkCSSMenu, " ", kGtkCSSMenuItem, ":disabled GtkLabel#label"})); + case ui::kColorAvatarIconGuest: + case ui::kColorMenuItemForegroundSecondary: + if (GtkCheckVersion(3, 20)) { + return GetFgColor( + StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, " #accelerator"})); + } + return GetFgColor(StrCat( + {kGtkCSSMenu, " ", kGtkCSSMenuItem, " GtkLabel#label.accelerator"})); + case ui::kColorMenuSeparator: + case ui::kColorAvatarHeaderArt: + if (GtkCheckVersion(3, 20)) { + return GetSeparatorColor( + StrCat({kGtkCSSMenu, " GtkSeparator#separator.horizontal"})); + } + return GetFgColor( + StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ".separator"})); + + // Dropdown + case ui::kColorDropdownBackground: + return GetBgColor( + StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ", + "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem, + " ", "GtkCellView#cellview"})); + case ui::kColorDropdownForeground: + return GetFgColor( + StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ", + "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem, + " ", "GtkCellView#cellview"})); + case ui::kColorDropdownBackgroundSelected: + return GetBgColor( + StrCat({"GtkComboBoxText#combobox GtkWindow#window.background.popup ", + "GtkTreeMenu#menu(gtk-combobox-popup-menu) ", kGtkCSSMenuItem, + ":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"})); + + // Label + case ui::kColorLabelForeground: + case ui::kColorPrimaryForeground: + return GetFgColor("GtkLabel#label"); + case ui::kColorLabelForegroundDisabled: + case ui::kColorLabelForegroundSecondary: + case ui::kColorDisabledForeground: + case ui::kColorSecondaryForeground: + return GetFgColor("GtkLabel#label:disabled"); + case ui::kColorLabelSelectionForeground: + return GetFgColor(GtkCheckVersion(3, 20) ? "GtkLabel#label #selection" + : "GtkLabel#label:selected"); + case ui::kColorLabelSelectionBackground: + return GetSelectionBgColor(GtkCheckVersion(3, 20) + ? "GtkLabel#label #selection" + : "GtkLabel#label:selected"); + + // Link + case ui::kColorLinkForegroundDisabled: + if (GtkCheckVersion(3, 12)) + return GetFgColor("GtkLabel#label.link:link:disabled"); + FALLTHROUGH; + case ui::kColorLinkForegroundPressed: + if (GtkCheckVersion(3, 12)) + return GetFgColor("GtkLabel#label.link:link:hover:active"); + FALLTHROUGH; + 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); + 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. + 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); + } + + // Scrollbar + case ui::kColorOverlayScrollbarStroke: + return GetBgColor("#GtkScrollbar#scrollbar #trough"); + case ui::kColorOverlayScrollbarStrokeHovered: + return GetBgColor("#GtkScrollbar#scrollbar #trough:hover"); + case ui::kColorOverlayScrollbarFill: + return GetBgColor("#GtkScrollbar#scrollbar #slider"); + case ui::kColorOverlayScrollbarFillHovered: + return GetBgColor("#GtkScrollbar#scrollbar #slider:hover"); + + // Slider + case ui::kColorSliderThumb: + return GetBgColor("GtkScale#scale #highlight"); + case ui::kColorSliderTrack: + return GetBgColor("GtkScale#scale #trough"); + case ui::kColorSliderThumbMinimal: + return GetBgColor("GtkScale#scale:disabled #highlight"); + case ui::kColorSliderTrackMinimal: + return GetBgColor("GtkScale#scale:disabled #trough"); + + // Separator + case ui::kColorMidground: + case ui::kColorSeparator: + return GetSeparatorColor("GtkSeparator#separator.horizontal"); + + // Button + case ui::kColorButtonBackground: + return GetBgColor("GtkButton#button"); + case ui::kColorButtonForeground: + case ui::kColorButtonForegroundUnchecked: + return GetFgColor("GtkButton#button.text-button GtkLabel#label"); + case ui::kColorButtonForegroundDisabled: + return GetFgColor("GtkButton#button.text-button:disabled GtkLabel#label"); + // TODO(thomasanderson): Add this once this CL lands: + // https://chromium-review.googlesource.com/c/chromium/src/+/2053144 + // case ui::kColorId_ButtonHoverColor: + // return GetBgColor("GtkButton#button:hover"); + + // ProminentButton + case ui::kColorAccent: + case ui::kColorButtonForegroundChecked: + case ui::kColorButtonBackgroundProminent: + case ui::kColorButtonBackgroundProminentFocused: + case ui::kColorNotificationInputBackground: + return GetBgColor( + "GtkTreeView#treeview.view " + "GtkTreeView#treeview.view.cell:selected:focus"); + case ui::kColorButtonForegroundProminent: + case ui::kColorNotificationInputForeground: + return GetFgColor( + "GtkTreeView#treeview.view " + "GtkTreeView#treeview.view.cell:selected:focus GtkLabel#label"); + case ui::kColorButtonBackgroundProminentDisabled: + case ui::kColorButtonBorderDisabled: + return GetBgColor("GtkButton#button.text-button:disabled"); + case ui::kColorButtonBorder: + return GetBorderColor("GtkButton#button.text-button"); + // TODO(thomasanderson): Add this once this CL lands: + // https://chromium-review.googlesource.com/c/chromium/src/+/2053144 + // case ui::kColorId_ProminentButtonHoverColor: + // return GetBgColor( + // "GtkTreeView#treeview.view " + // "GtkTreeView#treeview.view.cell:selected:focus:hover"); + + // ToggleButton + case ui::kColorToggleButtonTrackOff: + return GetBgColor("GtkButton#button.text-button.toggle"); + case ui::kColorToggleButtonTrackOn: + return GetBgColor("GtkButton#button.text-button.toggle:checked"); + + // TabbedPane + case ui::kColorTabForegroundSelected: + return GetFgColor("GtkLabel#label"); + case ui::kColorTabForeground: + return GetFgColor("GtkLabel#label:disabled"); + case ui::kColorTabContentSeparator: + return GetBorderColor(GtkCheckVersion(3, 20) ? "GtkFrame#frame #border" + : "GtkFrame#frame"); + case ui::kColorTabBackgroundHighlighted: + return GetBgColor("GtkNotebook#notebook #tab:checked"); + case ui::kColorTabBackgroundHighlightedFocused: + return GetBgColor("GtkNotebook#notebook:focus #tab:checked"); + + // Textfield + case ui::kColorTextfieldForeground: + return GetFgColor(GtkCheckVersion(3, 20) + ? "GtkTextView#textview.view #text" + : "GtkTextView.view"); + case ui::kColorTextfieldBackground: + return GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view" + : "GtkTextView.view"); + case ui::kColorTextfieldForegroundPlaceholder: + if (!GtkCheckVersion(3, 90)) { + 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 GetFgColor("GtkEntry#entry #text #placeholder"); + case ui::kColorTextfieldForegroundDisabled: + return GetFgColor(GtkCheckVersion(3, 20) + ? "GtkTextView#textview.view:disabled #text" + : "GtkTextView.view:disabled"); + case ui::kColorTextfieldBackgroundDisabled: + return GetBgColor(GtkCheckVersion(3, 20) + ? "GtkTextView#textview.view:disabled" + : "GtkTextView.view:disabled"); + case ui::kColorTextfieldSelectionForeground: + return GetFgColor(GtkCheckVersion(3, 20) + ? "GtkTextView#textview.view #text #selection" + : "GtkTextView.view:selected"); + case ui::kColorTextfieldSelectionBackground: + return GetSelectionBgColor( + GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text #selection" + : "GtkTextView.view:selected"); + + // Tooltips + case ui::kColorTooltipBackground: + return GetBgColorFromStyleContext(GetTooltipContext()); + case ui::kColorHelpIconInactive: + return GetFgColor("GtkButton#button.image-button"); + case ui::kColorHelpIconActive: + return GetFgColor("GtkButton#button.image-button:hover"); + case ui::kColorTooltipForeground: { + auto context = GetTooltipContext(); + context = AppendCssNodeToStyleContext(context, "GtkLabel#label"); + return GetFgColorFromStyleContext(context); + } + + // Trees and Tables (implemented on GTK using the same class) + case ui::kColorTableBackground: + case ui::kColorTableBackgroundAlternate: + case ui::kColorTreeBackground: + return GetBgColor( + "GtkTreeView#treeview.view GtkTreeView#treeview.view.cell"); + case ui::kColorTableForeground: + case ui::kColorTreeNodeForeground: + case ui::kColorTableGroupingIndicator: + return GetFgColor( + "GtkTreeView#treeview.view GtkTreeView#treeview.view.cell " + "GtkLabel#label"); + case ui::kColorTableForegroundSelectedFocused: + case ui::kColorTableForegroundSelectedUnfocused: + case ui::kColorTreeNodeForegroundSelectedFocused: + case ui::kColorTreeNodeForegroundSelectedUnfocused: + return GetFgColor( + "GtkTreeView#treeview.view " + "GtkTreeView#treeview.view.cell:selected:focus GtkLabel#label"); + case ui::kColorTableBackgroundSelectedFocused: + case ui::kColorTableBackgroundSelectedUnfocused: + case ui::kColorTreeNodeBackgroundSelectedFocused: + case ui::kColorTreeNodeBackgroundSelectedUnfocused: + return GetBgColor( + "GtkTreeView#treeview.view " + "GtkTreeView#treeview.view.cell:selected:focus"); + + // Table Header + case ui::kColorTableHeaderForeground: + return GetFgColor( + "GtkTreeView#treeview.view GtkButton#button GtkLabel#label"); + case ui::kColorTableHeaderBackground: + return GetBgColor("GtkTreeView#treeview.view GtkButton#button"); + case ui::kColorTableHeaderSeparator: + return GetBorderColor("GtkTreeView#treeview.view GtkButton#button"); + + // Throbber + // TODO(thomasanderson): Render GtkSpinner directly. + case ui::kColorThrobber: + return GetFgColor("GtkSpinner#spinner"); + case ui::kColorThrobberPreconnect: + return GetFgColor("GtkSpinner#spinner:disabled"); + + // Alert icons + // Fallback to the same colors as Aura. + case ui::kColorAlertLowSeverity: + case ui::kColorAlertMediumSeverity: + case ui::kColorAlertHighSeverity: { + // Alert icons appear on the toolbar, so use the toolbar BG + // color (the GTK window bg color) to determine if the dark + // or light native theme should be used for the icons. + return ui::GetAlertSeverityColor(color_id, + color_utils::IsDark(GetBgColor(""))); + } + + case ui::kColorMenuIcon: + if (GtkCheckVersion(3, 20)) + return GetFgColor( + StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, " #radio"})); + return GetFgColor(StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ".radio"})); + + case ui::kColorIcon: + return GetFgColor("GtkButton#button.flat.scale GtkImage#image"); + + default: + break; + } + return base::nullopt; +} + } // namespace gtk diff --git a/chromium/ui/gtk/gtk_util.h b/chromium/ui/gtk/gtk_util.h index df6cac5ba32..67550b1fd24 100644 --- a/chromium/ui/gtk/gtk_util.h +++ b/chromium/ui/gtk/gtk_util.h @@ -11,14 +11,14 @@ #include #include +#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" -// Function availability can be tested by checking if the address of gtk_* is -// not nullptr. -#define WEAK_GTK_FN(x) extern "C" __attribute__((weak)) decltype(x) x - namespace aura { class Window; } @@ -33,6 +33,11 @@ class KeyEvent; namespace gtk { +extern const char kGtkCSSMenu[]; +extern const char kGtkCSSMenuItem[]; +extern const char kGtkCSSMenuScrollbar[]; + +COMPONENT_EXPORT(GTK) void GtkInitFromCommandLine(const base::CommandLine& command_line); // Sets |dialog| as transient for |parent|, which will keep it on top and center @@ -78,19 +83,51 @@ class CairoSurface { cairo_t* cairo_; }; -// Returns true iff the runtime version of Gtk used meets -// |major|.|minor|.|micro|. -bool GtkCheckVersion(int major, int minor = 0, int micro = 0); +class GtkCssContext { + public: + GtkCssContext(); + GtkCssContext(const GtkCssContext&); + GtkCssContext(GtkCssContext&&); + GtkCssContext& operator=(const GtkCssContext&); + GtkCssContext& operator=(GtkCssContext&&); + ~GtkCssContext(); + + // GTK3 constructor. + explicit GtkCssContext(GtkStyleContext* context); + + // GTK4 constructor. + GtkCssContext(GtkWidget* widget, GtkWidget* root); + + // As a convenience, allow using a GtkCssContext as a gtk_style_context() + // to avoid repeated use of an explicit getter. + // NOLINTNEXTLINE(google-explicit-constructor) + operator GtkStyleContext*(); + + GtkCssContext GetParent(); + + // Only available on GTK4. + GtkWidget* widget(); + GtkWidget* root(); + + private: + // GTK3 state. + ScopedGObject context_; + + // GTK4 state. + // GTK widgets own their children, so instead of keeping a reference to the + // widget directly, keep a reference to the root widget. + GtkWidget* widget_ = nullptr; + ScopedGObject root_; +}; -using ScopedStyleContext = ScopedGObject; using ScopedCssProvider = ScopedGObject; -#if !GTK_CHECK_VERSION(3, 90, 0) +#if BUILDFLAG(GTK_VERSION) < 4 } // namespace gtk // Template override cannot be in the gtk namespace. template <> -inline void gtk::ScopedStyleContext::Unref() { +inline void ScopedGObject::Unref() { // Versions of GTK earlier than 3.15.4 had a bug where a g_assert // would be triggered when trying to free a GtkStyleContext that had // a parent whose only reference was the child context in question. @@ -123,24 +160,24 @@ 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. -ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context, - const std::string& css_node); +GtkCssContext AppendCssNodeToStyleContext(GtkCssContext context, + const std::string& css_node); -// Parses |css_selector| into a GtkStyleContext. The format is a +// Parses |css_selector| into a StyleContext. The format is a // sequence of whitespace-separated objects. Each object may have at // most one object name at the beginning of the string, and any number // of '.'-prefixed classes and ':'-prefixed pseudoclasses. An example // is "GtkButton.button.suggested-action:hover:active". The caller // must g_object_unref() the returned context. -ScopedStyleContext GetStyleContextFromCss(const std::string& css_selector); +GtkCssContext GetStyleContextFromCss(const std::string& css_selector); SkColor GetFgColorFromStyleContext(GtkStyleContext* context); -SkColor GetBgColorFromStyleContext(GtkStyleContext* context); +SkColor GetBgColorFromStyleContext(GtkCssContext context); // Overrides properties on |context| and all its parents with those // provided by |css|. -void ApplyCssToContext(GtkStyleContext* context, const std::string& css); +void ApplyCssToContext(GtkCssContext context, const std::string& css); // Get the 'color' property from the style context created by // GetStyleContextFromCss(|css_selector|). @@ -152,7 +189,7 @@ ScopedCssProvider GetCssProvider(const std::string& css); // the background for |context| itself. void RenderBackground(const gfx::Size& size, cairo_t* cr, - GtkStyleContext* context); + GtkCssContext context); // Renders a background from the style context created by // GetStyleContextFromCss(|css_selector|) into a 24x24 bitmap and @@ -186,15 +223,34 @@ std::string GetGtkSettingsStringProperty(GtkSettings* settings, // https://gitlab.freedesktop.org/xorg/proto/xorgproto/blob/master/include/X11/extensions/XKB.h#L372 int BuildXkbStateFromGdkEvent(unsigned int state, unsigned char group); +int GetKeyEventProperty(const ui::KeyEvent& key_event, + const char* property_key); + +GdkModifierType GetGdkKeyEventState(const ui::KeyEvent& key_event); + // Translates |key_event| into a GdkEvent. GdkEvent::key::window is the only // field not set by this function, callers must set it, as the way for // retrieving it may vary depending on the event being processed. E.g: for IME // Context impl, X11 window XID is obtained through Event::target() which is -// root aura::Window targeted by that key event. +// root aura::Window targeted by that key event. Only available in GTK3. GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event); GtkIconTheme* GetDefaultIconTheme(); +void GtkWindowDestroy(GtkWidget* widget); + +GtkWidget* GetDummyWindow(); + +gfx::Size GetSeparatorSize(bool horizontal); + +float GetDeviceScaleFactor(); + +// This should only be called on Gtk4. +GdkTexture* GetTextureFromRenderNode(GskRenderNode* node); + +// Gets the GTK theme color for a given `color_id`. +base::Optional SkColorFromColorId(ui::ColorId color_id); + } // namespace gtk #endif // UI_GTK_GTK_UTIL_H_ diff --git a/chromium/ui/gtk/input_method_context_impl_gtk.cc b/chromium/ui/gtk/input_method_context_impl_gtk.cc index 332d171ef3b..4346c07488e 100644 --- a/chromium/ui/gtk/input_method_context_impl_gtk.cc +++ b/chromium/ui/gtk/input_method_context_impl_gtk.cc @@ -15,9 +15,11 @@ #include "ui/base/ime/linux/composition_text_util_pango.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/event.h" +#include "ui/events/event_utils.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/rect_conversions.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_util.h" @@ -27,6 +29,13 @@ namespace gtk { namespace { +GdkEventKey* GdkEventToKey(GdkEvent* event) { + DCHECK(!GtkCheckVersion(4)); + auto* key = reinterpret_cast(event); + DCHECK(key->type == GDK_KEY_PRESS || key->type == GDK_KEY_RELEASE); + return key; +} + // Get IME KeyEvent's target window. Assumes root aura::Window is set to // Event::target(), otherwise returns null. GdkWindow* GetTargetWindow(const ui::KeyEvent& key_event) { @@ -42,6 +51,7 @@ GdkWindow* GetTargetWindow(const ui::KeyEvent& key_event) { // Translate IME ui::KeyEvent to a GdkEventKey. GdkEvent* GdkEventFromImeKeyEvent(const ui::KeyEvent& key_event) { + DCHECK(!GtkCheckVersion(4)); GdkEvent* event = GdkEventFromKeyEvent(key_event); if (!event) return nullptr; @@ -51,7 +61,7 @@ GdkEvent* GdkEventFromImeKeyEvent(const ui::KeyEvent& key_event) { gdk_event_free(event); return nullptr; } - event->key.window = target_window; + GdkEventToKey(event)->window = target_window; return event; } @@ -60,11 +70,7 @@ GdkEvent* GdkEventFromImeKeyEvent(const ui::KeyEvent& key_event) { InputMethodContextImplGtk::InputMethodContextImplGtk( ui::LinuxInputMethodContextDelegate* delegate, bool is_simple) - : delegate_(delegate), - is_simple_(is_simple), - has_focus_(false), - gtk_context_(nullptr), - gdk_last_set_client_window_(nullptr) { + : delegate_(delegate), is_simple_(is_simple) { CHECK(delegate_); gtk_context_ = @@ -80,6 +86,9 @@ InputMethodContextImplGtk::InputMethodContextImplGtk( // TODO(shuchen): Handle operations on surrounding text. // "delete-surrounding" and "retrieve-surrounding" signals should be // handled. + + if (GtkCheckVersion(4)) + gtk_im_context_set_client_widget(gtk_context_, GetDummyWindow()); } InputMethodContextImplGtk::~InputMethodContextImplGtk() { @@ -95,39 +104,64 @@ bool InputMethodContextImplGtk::DispatchKeyEvent( if (!gtk_context_) return false; - GdkEvent* event = GdkEventFromImeKeyEvent(key_event); - if (!event) { - LOG(ERROR) << "Cannot translate a Keyevent to a GdkEvent."; - return false; - } - - GdkWindow* target_window = event->key.window; - if (!target_window) { - LOG(ERROR) << "Cannot get target GdkWindow for KeyEvent."; - return false; + GdkEvent* event = nullptr; + if (!GtkCheckVersion(4)) { + event = GdkEventFromImeKeyEvent(key_event); + if (!event) { + LOG(ERROR) << "Cannot translate a Keyevent to a GdkEvent."; + return false; + } + + GdkWindow* target_window = GdkEventToKey(event)->window; + if (!target_window) { + LOG(ERROR) << "Cannot get target GdkWindow for KeyEvent."; + return false; + } + + SetContextClientWindow(target_window); } - SetContextClientWindow(target_window); - // Convert the last known caret bounds relative to the screen coordinates // to a GdkRectangle relative to the client window. - gint win_x = 0; - gint win_y = 0; - gdk_window_get_origin(target_window, &win_x, &win_y); - - gint factor = gdk_window_get_scale_factor(target_window); - gint caret_x = last_caret_bounds_.x() / factor; - gint caret_y = last_caret_bounds_.y() / factor; - gint caret_w = last_caret_bounds_.width() / factor; - gint caret_h = last_caret_bounds_.height() / factor; - - GdkRectangle gdk_rect = {caret_x - win_x, caret_y - win_y, caret_w, caret_h}; + aura::Window* window = static_cast(key_event.target()); + gint win_x = window->GetBoundsInScreen().x(); + gint win_y = window->GetBoundsInScreen().y(); + gint caret_x = last_caret_bounds_.x(); + gint caret_y = last_caret_bounds_.y(); + gint caret_w = last_caret_bounds_.width(); + gint caret_h = last_caret_bounds_.height(); + + // Chrome's DIPs may be different from GTK's DIPs if + // --force-device-scale-factor is used. + float factor = + GetDeviceScaleFactor() / gtk_widget_get_scale_factor(GetDummyWindow()); + GdkRectangle gdk_rect = {factor * (caret_x - win_x), + factor * (caret_y - win_y), factor * caret_w, + factor * caret_h}; gtk_im_context_set_cursor_location(gtk_context_, &gdk_rect); - const bool handled = - gtk_im_context_filter_keypress(gtk_context_, &event->key); - gdk_event_free(event); - return handled; + if (!GtkCheckVersion(4)) { + const bool handled = + GtkImContextFilterKeypress(gtk_context_, GdkEventToKey(event)); + gdk_event_free(event); + return handled; + } + // In GTK4, clients can no longer create or modify events. This makes using + // the gtk_im_context_filter_keypress() API impossible. Fortunately, an + // alternative API called gtk_im_context_filter_key() was added for clients + // that would have needed to construct their own event. The parameters to + // the new API are just a deconstructed version of a KeyEvent. + bool press = key_event.type() == ui::ET_KEY_PRESSED; + auto* surface = + gtk_native_get_surface(gtk_widget_get_native(GetDummyWindow())); + auto* device = gdk_seat_get_keyboard( + gdk_display_get_default_seat(gdk_display_get_default())); + auto time = (key_event.time_stamp() - base::TimeTicks()).InMilliseconds(); + auto keycode = GetKeyEventProperty(key_event, ui::kPropertyKeyboardHwKeyCode); + auto state = GetGdkKeyEventState(key_event); + auto group = GetKeyEventProperty(key_event, ui::kPropertyKeyboardGroup); + return gtk_im_context_filter_key(gtk_context_, press, surface, device, time, + keycode, state, group); } void InputMethodContextImplGtk::Reset() { @@ -155,18 +189,13 @@ void InputMethodContextImplGtk::SetCursorLocation(const gfx::Rect& rect) { // Remember the caret bounds so that we can set the cursor location later. // gtk_im_context_set_cursor_location() takes the location relative to the // client window, which is unknown at this point. So we'll call - // gtk_im_context_set_cursor_location() later in ProcessKeyEvent() where + // gtk_im_context_set_cursor_location() later in DispatchKeyEvent() where // (and only where) we know the client window. - if (views::LinuxUI::instance()) { - last_caret_bounds_ = gfx::ToEnclosingRect(gfx::ConvertRectToPixels( - rect, views::LinuxUI::instance()->GetDeviceScaleFactor())); - } else { - last_caret_bounds_ = rect; - } + last_caret_bounds_ = rect; } void InputMethodContextImplGtk::SetSurroundingText( - const base::string16& text, + const std::u16string& text, const gfx::Range& selection_range) {} // private: @@ -212,14 +241,10 @@ void InputMethodContextImplGtk::OnPreeditStart(GtkIMContext* context) { } void InputMethodContextImplGtk::SetContextClientWindow(GdkWindow* window) { + DCHECK(!GtkCheckVersion(4)); if (window == gdk_last_set_client_window_) return; -#if GTK_CHECK_VERSION(3, 90, 0) - asdf; - gtk_im_context_set_client_widget(gtk_context_, GTK_WIDGET(window)); -#else gtk_im_context_set_client_window(gtk_context_, window); -#endif // Prevent leaks when overriding last client window if (gdk_last_set_client_window_) diff --git a/chromium/ui/gtk/input_method_context_impl_gtk.h b/chromium/ui/gtk/input_method_context_impl_gtk.h index 1034b7412ff..2fb3356649e 100644 --- a/chromium/ui/gtk/input_method_context_impl_gtk.h +++ b/chromium/ui/gtk/input_method_context_impl_gtk.h @@ -5,21 +5,17 @@ #ifndef UI_GTK_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ #define UI_GTK_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ +#include + #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/base/glib/glib_integers.h" #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" -typedef struct _GtkIMContext GtkIMContext; - -#if BUILDFLAG(GTK_VERSION) == 3 +using GtkIMContext = struct _GtkIMContext; using GdkWindow = struct _GdkWindow; -#else -using GdkWindow = struct _GdkSurface; -#endif namespace gtk { @@ -37,7 +33,7 @@ class InputMethodContextImplGtk : public ui::LinuxInputMethodContext { void Reset() override; void Focus() override; void Blur() override; - void SetSurroundingText(const base::string16& text, + void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; private: @@ -61,25 +57,27 @@ class InputMethodContextImplGtk : public ui::LinuxInputMethodContext { OnPreeditStart, GtkIMContext*); + // Only used on GTK3. void SetContextClientWindow(GdkWindow* window); // A set of callback functions. Must not be nullptr. - ui::LinuxInputMethodContextDelegate* delegate_; + ui::LinuxInputMethodContextDelegate* const delegate_; // Input method context type flag. // - true if it supports table-based input methods // - false if it supports multiple, loadable input methods - bool is_simple_; + const bool is_simple_; // Keeps track of current focus state. - bool has_focus_; + bool has_focus_ = false; // IME's input GTK context. - GtkIMContext* gtk_context_; + GtkIMContext* gtk_context_ = nullptr; - gpointer gdk_last_set_client_window_; + // Only used on GTK3. + gpointer gdk_last_set_client_window_ = nullptr; - // Last known caret bounds relative to the screen coordinates. + // Last known caret bounds relative to the screen coordinates, in DIPs. gfx::Rect last_caret_bounds_; DISALLOW_COPY_AND_ASSIGN(InputMethodContextImplGtk); diff --git a/chromium/ui/gtk/log_noop.h b/chromium/ui/gtk/log_noop.h new file mode 100644 index 00000000000..ba7b746180a --- /dev/null +++ b/chromium/ui/gtk/log_noop.h @@ -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. + +#ifndef UI_GTK_LOG_NOOP_H_ +#define UI_GTK_LOG_NOOP_H_ + +// This is a no-op logger used to ignore error messages reported by generated +// stub initializers. Some missing symbols are expected since they may only be +// available in specific versions of GTK. +struct LogNoop { + template + LogNoop operator<<(const T& t) { + return *this; + } +}; + +#endif // UI_GTK_LOG_NOOP_H_ diff --git a/chromium/ui/gtk/native_theme_gtk.cc b/chromium/ui/gtk/native_theme_gtk.cc index 29ad448b157..7efdd8cf94e 100644 --- a/chromium/ui/gtk/native_theme_gtk.cc +++ b/chromium/ui/gtk/native_theme_gtk.cc @@ -6,12 +6,20 @@ #include +#include "base/strings/strcat.h" +#include "ui/color/color_provider_manager.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/skia_util.h" +#include "ui/gtk/gtk_color_mixers.h" +#include "ui/gtk/gtk_compat.h" #include "ui/gtk/gtk_util.h" +#include "ui/native_theme/common_theme.h" #include "ui/native_theme/native_theme_aura.h" +#include "ui/native_theme/native_theme_utils.h" + +using base::StrCat; namespace gtk { @@ -23,14 +31,8 @@ enum BackgroundRenderMode { BG_RENDER_RECURSIVE, }; -ScopedStyleContext GetTooltipContext() { - return AppendCssNodeToStyleContext( - nullptr, GtkCheckVersion(3, 20) ? "#tooltip.background" - : "GtkWindow#window.background.tooltip"); -} - SkBitmap GetWidgetBitmap(const gfx::Size& size, - GtkStyleContext* context, + GtkCssContext context, BackgroundRenderMode bg_mode, bool render_frame) { DCHECK(bg_mode != BG_RENDER_NONE || render_frame); @@ -59,7 +61,7 @@ SkBitmap GetWidgetBitmap(const gfx::Size& size, void PaintWidget(cc::PaintCanvas* canvas, const gfx::Rect& rect, - GtkStyleContext* context, + GtkCssContext context, BackgroundRenderMode bg_mode, bool render_frame) { canvas->drawImage(cc::PaintImage::CreateFromBitmap(GetWidgetBitmap( @@ -67,337 +69,6 @@ void PaintWidget(cc::PaintCanvas* canvas, rect.x(), rect.y()); } -base::Optional SkColorFromColorId( - ui::NativeTheme::ColorId color_id, - const ui::NativeTheme* base_theme, - ui::NativeTheme::ColorScheme color_scheme) { - switch (color_id) { - // Windows - case ui::NativeTheme::kColorId_WindowBackground: - // Dialogs - case ui::NativeTheme::kColorId_DialogBackground: - case ui::NativeTheme::kColorId_BubbleBackground: - // Notifications - case ui::NativeTheme::kColorId_NotificationDefaultBackground: - return GetBgColor(""); - case ui::NativeTheme::kColorId_DialogForeground: - case ui::NativeTheme::kColorId_AvatarIconIncognito: - return GetFgColor("GtkLabel"); - case ui::NativeTheme::kColorId_BubbleFooterBackground: - return GetBgColor("#statusbar"); - - // FocusableBorder - case ui::NativeTheme::kColorId_FocusedBorderColor: - // GetBorderColor("GtkEntry#entry:focus") is correct here. The focus ring - // around widgets is usually a lighter version of the "canonical theme - // color" - orange on Ambiance, blue on Adwaita, etc. However, Chrome - // lightens the color we give it, so it would look wrong if we give it an - // already-lightened color. This workaround returns the theme color - // directly, taken from a selected table row. This has matched the theme - // color on every theme that I've tested. - return GetBgColor( - "GtkTreeView#treeview.view " - "GtkTreeView#treeview.view.cell:selected:focus"); - case ui::NativeTheme::kColorId_UnfocusedBorderColor: - return GetBorderColor("GtkEntry#entry"); - - // Menu - case ui::NativeTheme::kColorId_MenuBackgroundColor: - case ui::NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: - case ui::NativeTheme::kColorId_MenuItemInitialAlertBackgroundColor: - case ui::NativeTheme::kColorId_MenuItemTargetAlertBackgroundColor: - return GetBgColor("GtkMenu#menu"); - case ui::NativeTheme::kColorId_MenuBorderColor: - return GetBorderColor("GtkMenu#menu"); - case ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor: - return GetBgColor("GtkMenu#menu GtkMenuItem#menuitem:hover"); - case ui::NativeTheme::kColorId_EnabledMenuItemForegroundColor: - case ui::NativeTheme::kColorId_MenuDropIndicator: - case ui::NativeTheme::kColorId_HighlightedMenuItemForegroundColor: - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem GtkLabel"); - case ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor: - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem:hover GtkLabel"); - case ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor: - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem:disabled GtkLabel"); - case ui::NativeTheme::kColorId_AvatarIconGuest: - case ui::NativeTheme::kColorId_MenuItemMinorTextColor: - if (GtkCheckVersion(3, 20)) { - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem #accelerator"); - } - return GetFgColor( - "GtkMenu#menu GtkMenuItem#menuitem GtkLabel.accelerator"); - case ui::NativeTheme::kColorId_MenuSeparatorColor: - case ui::NativeTheme::kColorId_AvatarHeaderArt: - if (GtkCheckVersion(3, 20)) { - return GetSeparatorColor( - "GtkMenu#menu GtkSeparator#separator.horizontal"); - } - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem.separator"); - - // Dropdown - case ui::NativeTheme::kColorId_DropdownBackgroundColor: - return GetBgColor( - "GtkComboBoxText#combobox GtkWindow#window.background.popup " - "GtkTreeMenu#menu(gtk-combobox-popup-menu) GtkMenuItem#menuitem " - "GtkCellView#cellview"); - case ui::NativeTheme::kColorId_DropdownForegroundColor: - return GetFgColor( - "GtkComboBoxText#combobox GtkWindow#window.background.popup " - "GtkTreeMenu#menu(gtk-combobox-popup-menu) GtkMenuItem#menuitem " - "GtkCellView#cellview"); - case ui::NativeTheme::kColorId_DropdownSelectedBackgroundColor: - return GetBgColor( - "GtkComboBoxText#combobox GtkWindow#window.background.popup " - "GtkTreeMenu#menu(gtk-combobox-popup-menu) " - "GtkMenuItem#menuitem:hover GtkCellView#cellview"); - case ui::NativeTheme::kColorId_DropdownSelectedForegroundColor: - return GetFgColor( - "GtkComboBoxText#combobox GtkWindow#window.background.popup " - "GtkTreeMenu#menu(gtk-combobox-popup-menu) " - "GtkMenuItem#menuitem:hover GtkCellView#cellview"); - - // Label - case ui::NativeTheme::kColorId_LabelEnabledColor: - return GetFgColor("GtkLabel"); - case ui::NativeTheme::kColorId_LabelDisabledColor: - case ui::NativeTheme::kColorId_LabelSecondaryColor: - return GetFgColor("GtkLabel:disabled"); - case ui::NativeTheme::kColorId_LabelTextSelectionColor: - return GetFgColor(GtkCheckVersion(3, 20) ? "GtkLabel #selection" - : "GtkLabel:selected"); - case ui::NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: - return GetSelectionBgColor(GtkCheckVersion(3, 20) ? "GtkLabel #selection" - : "GtkLabel:selected"); - - // Link - case ui::NativeTheme::kColorId_LinkDisabled: - return SkColorSetA( - base_theme->GetSystemColor(ui::NativeTheme::kColorId_LinkEnabled, - color_scheme), - 0xBB); - case ui::NativeTheme::kColorId_LinkPressed: - if (GtkCheckVersion(3, 12)) - return GetFgColor("GtkLabel.link:link:hover:active"); - FALLTHROUGH; - case ui::NativeTheme::kColorId_LinkEnabled: { - if (GtkCheckVersion(3, 12)) - return GetFgColor("GtkLabel.link:link"); -#if !GTK_CHECK_VERSION(3, 90, 0) - auto link_context = GetStyleContextFromCss("GtkLabel.view"); - GdkColor* color; - gtk_style_context_get_style(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. - 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); - } - - // Scrollbar - case ui::NativeTheme::kColorId_OverlayScrollbarThumbBackground: - return GetBgColor("#GtkScrollbar#scrollbar #trough"); - case ui::NativeTheme::kColorId_OverlayScrollbarThumbForeground: - return GetBgColor("#GtkScrollbar#scrollbar #slider"); - - // Slider - case ui::NativeTheme::kColorId_SliderThumbDefault: - return GetBgColor("GtkScale#scale #highlight"); - case ui::NativeTheme::kColorId_SliderTroughDefault: - return GetBgColor("GtkScale#scale #trough"); - case ui::NativeTheme::kColorId_SliderThumbMinimal: - return GetBgColor("GtkScale#scale:disabled #highlight"); - case ui::NativeTheme::kColorId_SliderTroughMinimal: - return GetBgColor("GtkScale#scale:disabled #trough"); - - // Separator - case ui::NativeTheme::kColorId_SeparatorColor: - return GetSeparatorColor("GtkSeparator#separator.horizontal"); - - // Button - case ui::NativeTheme::kColorId_ButtonColor: - return GetBgColor("GtkButton#button"); - case ui::NativeTheme::kColorId_ButtonEnabledColor: - case ui::NativeTheme::kColorId_ButtonUncheckedColor: - return GetFgColor("GtkButton#button.text-button GtkLabel"); - case ui::NativeTheme::kColorId_ButtonDisabledColor: - return GetFgColor("GtkButton#button.text-button:disabled GtkLabel"); - // TODO(thomasanderson): Add this once this CL lands: - // https://chromium-review.googlesource.com/c/chromium/src/+/2053144 - // case ui::NativeTheme::kColorId_ButtonHoverColor: - // return GetBgColor("GtkButton#button:hover"); - - // ProminentButton - case ui::NativeTheme::kColorId_ButtonCheckedColor: - case ui::NativeTheme::kColorId_ProminentButtonColor: - case ui::NativeTheme::kColorId_ProminentButtonFocusedColor: - return GetBgColor( - "GtkTreeView#treeview.view " - "GtkTreeView#treeview.view.cell:selected:focus"); - case ui::NativeTheme::kColorId_TextOnProminentButtonColor: - return GetFgColor( - "GtkTreeView#treeview.view " - "GtkTreeView#treeview.view.cell:selected:focus GtkLabel"); - case ui::NativeTheme::kColorId_ProminentButtonDisabledColor: - return GetBgColor("GtkButton#button.text-button:disabled"); - case ui::NativeTheme::kColorId_ButtonBorderColor: - return GetBorderColor("GtkButton#button.text-button"); - // TODO(thomasanderson): Add this once this CL lands: - // https://chromium-review.googlesource.com/c/chromium/src/+/2053144 - // case ui::NativeTheme::kColorId_ProminentButtonHoverColor: - // return GetBgColor( - // "GtkTreeView#treeview.view " - // "GtkTreeView#treeview.view.cell:selected:focus:hover"); - - // ToggleButton - case ui::NativeTheme::kColorId_ToggleButtonTrackColorOff: - return GetBgColor("GtkButton#button.text-button.toggle"); - case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: - return GetBgColor("GtkButton#button.text-button.toggle:checked"); - - // TabbedPane - case ui::NativeTheme::kColorId_TabTitleColorActive: - return GetFgColor("GtkLabel"); - case ui::NativeTheme::kColorId_TabTitleColorInactive: - return GetFgColor("GtkLabel:disabled"); - case ui::NativeTheme::kColorId_TabBottomBorder: - return GetBorderColor(GtkCheckVersion(3, 20) ? "GtkFrame#frame #border" - : "GtkFrame#frame"); - case ui::NativeTheme::kColorId_TabHighlightBackground: - return GetBgColor("GtkNotebook#notebook #tab:checked"); - case ui::NativeTheme::kColorId_TabHighlightFocusedBackground: - return GetBgColor("GtkNotebook#notebook:focus #tab:checked"); - - // Textfield - case ui::NativeTheme::kColorId_TextfieldDefaultColor: - return GetFgColor(GtkCheckVersion(3, 20) - ? "GtkTextView#textview.view #text" - : "GtkTextView.view"); - case ui::NativeTheme::kColorId_TextfieldDefaultBackground: - return GetBgColor(GtkCheckVersion(3, 20) ? "GtkTextView#textview.view" - : "GtkTextView.view"); - case ui::NativeTheme::kColorId_TextfieldPlaceholderColor: - if (!GtkCheckVersion(3, 90)) { - 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 GetFgColor("GtkEntry#entry #text #placeholder"); - case ui::NativeTheme::kColorId_TextfieldReadOnlyColor: - return GetFgColor(GtkCheckVersion(3, 20) - ? "GtkTextView#textview.view:disabled #text" - : "GtkTextView.view:disabled"); - case ui::NativeTheme::kColorId_TextfieldReadOnlyBackground: - return GetBgColor(GtkCheckVersion(3, 20) - ? "GtkTextView#textview.view:disabled" - : "GtkTextView.view:disabled"); - case ui::NativeTheme::kColorId_TextfieldSelectionColor: - return GetFgColor(GtkCheckVersion(3, 20) - ? "GtkTextView#textview.view #text #selection" - : "GtkTextView.view:selected"); - case ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused: - return GetSelectionBgColor( - GtkCheckVersion(3, 20) ? "GtkTextView#textview.view #text #selection" - : "GtkTextView.view:selected"); - - // Tooltips - case ui::NativeTheme::kColorId_TooltipBackground: - return GetBgColorFromStyleContext(GetTooltipContext()); - case ui::NativeTheme::kColorId_TooltipIcon: - return GetFgColor("GtkButton#button.image-button"); - case ui::NativeTheme::kColorId_TooltipIconHovered: - return GetFgColor("GtkButton#button.image-button:hover"); - case ui::NativeTheme::kColorId_TooltipText: { - auto context = GetTooltipContext(); - context = AppendCssNodeToStyleContext(context, "GtkLabel"); - return GetFgColorFromStyleContext(context); - } - - // Trees and Tables (implemented on GTK using the same class) - case ui::NativeTheme::kColorId_TableBackground: - case ui::NativeTheme::kColorId_TableBackgroundAlternate: - case ui::NativeTheme::kColorId_TreeBackground: - return GetBgColor( - "GtkTreeView#treeview.view GtkTreeView#treeview.view.cell"); - case ui::NativeTheme::kColorId_TableText: - case ui::NativeTheme::kColorId_TreeText: - case ui::NativeTheme::kColorId_TableGroupingIndicatorColor: - return GetFgColor( - "GtkTreeView#treeview.view GtkTreeView#treeview.view.cell GtkLabel"); - case ui::NativeTheme::kColorId_TableSelectedText: - case ui::NativeTheme::kColorId_TableSelectedTextUnfocused: - case ui::NativeTheme::kColorId_TreeSelectedText: - case ui::NativeTheme::kColorId_TreeSelectedTextUnfocused: - return GetFgColor( - "GtkTreeView#treeview.view " - "GtkTreeView#treeview.view.cell:selected:focus GtkLabel"); - case ui::NativeTheme::kColorId_TableSelectionBackgroundFocused: - case ui::NativeTheme::kColorId_TableSelectionBackgroundUnfocused: - case ui::NativeTheme::kColorId_TreeSelectionBackgroundFocused: - case ui::NativeTheme::kColorId_TreeSelectionBackgroundUnfocused: - return GetBgColor( - "GtkTreeView#treeview.view " - "GtkTreeView#treeview.view.cell:selected:focus"); - - // Table Header - case ui::NativeTheme::kColorId_TableHeaderText: - return GetFgColor("GtkTreeView#treeview.view GtkButton#button GtkLabel"); - case ui::NativeTheme::kColorId_TableHeaderBackground: - return GetBgColor("GtkTreeView#treeview.view GtkButton#button"); - case ui::NativeTheme::kColorId_TableHeaderSeparator: - return GetBorderColor("GtkTreeView#treeview.view GtkButton#button"); - - // Throbber - // TODO(thomasanderson): Render GtkSpinner directly. - case ui::NativeTheme::kColorId_ThrobberSpinningColor: - return GetFgColor("GtkSpinner#spinner"); - case ui::NativeTheme::kColorId_ThrobberWaitingColor: - case ui::NativeTheme::kColorId_ThrobberLightColor: - return GetFgColor("GtkSpinner#spinner:disabled"); - - // Alert icons - // Fallback to the same colors as Aura. - case ui::NativeTheme::kColorId_AlertSeverityLow: - case ui::NativeTheme::kColorId_AlertSeverityMedium: - case ui::NativeTheme::kColorId_AlertSeverityHigh: { - // Alert icons appear on the toolbar, so use the toolbar BG - // color (the GTK window bg color) to determine if the dark - // or light native theme should be used for the icons. - ui::NativeTheme* fallback_theme = - color_utils::IsDark(GetBgColor("")) - ? ui::NativeTheme::GetInstanceForDarkUI() - : ui::NativeTheme::GetInstanceForNativeUi(); - return fallback_theme->GetSystemColor(color_id); - } - - case ui::NativeTheme::kColorId_MenuIconColor: - if (GtkCheckVersion(3, 20)) - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem #radio"); - return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem.radio"); - - case ui::NativeTheme::kColorId_DefaultIconColor: - return GetFgColor("GtkButton#button.flat.scale GtkImage#image"); - - case ui::NativeTheme::kColorId_NumColors: - NOTREACHED(); - break; - - default: - break; - } - return base::nullopt; -} - } // namespace // static @@ -407,36 +78,43 @@ NativeThemeGtk* NativeThemeGtk::instance() { } NativeThemeGtk::NativeThemeGtk() { - // These types are needed by g_type_from_name(), but may not be registered at - // this point. We need the g_type_class magic to make sure the compiler - // doesn't optimize away this code. - g_type_class_unref(g_type_class_ref(gtk_button_get_type())); - g_type_class_unref(g_type_class_ref(gtk_entry_get_type())); - g_type_class_unref(g_type_class_ref(gtk_frame_get_type())); - g_type_class_unref(g_type_class_ref(gtk_header_bar_get_type())); - g_type_class_unref(g_type_class_ref(gtk_image_get_type())); - g_type_class_unref(g_type_class_ref(gtk_info_bar_get_type())); - g_type_class_unref(g_type_class_ref(gtk_label_get_type())); - g_type_class_unref(g_type_class_ref(gtk_menu_get_type())); - g_type_class_unref(g_type_class_ref(gtk_menu_bar_get_type())); - g_type_class_unref(g_type_class_ref(gtk_menu_item_get_type())); - g_type_class_unref(g_type_class_ref(gtk_range_get_type())); - g_type_class_unref(g_type_class_ref(gtk_scrollbar_get_type())); - g_type_class_unref(g_type_class_ref(gtk_scrolled_window_get_type())); - g_type_class_unref(g_type_class_ref(gtk_separator_get_type())); - g_type_class_unref(g_type_class_ref(gtk_spinner_get_type())); - g_type_class_unref(g_type_class_ref(gtk_text_view_get_type())); - g_type_class_unref(g_type_class_ref(gtk_toggle_button_get_type())); - g_type_class_unref(g_type_class_ref(gtk_tree_view_get_type())); - g_type_class_unref(g_type_class_ref(gtk_window_get_type())); - g_type_class_unref(g_type_class_ref(gtk_combo_box_text_get_type())); - g_type_class_unref(g_type_class_ref(gtk_cell_view_get_type())); - - // Initialize the GtkTreeMenu type. _gtk_tree_menu_get_type() is private, so - // we need to initialize it indirectly. - ScopedGObject model{ - GTK_TREE_MODEL(gtk_tree_store_new(1, G_TYPE_STRING))}; - ScopedGObject combo{gtk_combo_box_new_with_model(model)}; + // g_type_from_name() is only used in GTK3. + if (!GtkCheckVersion(4)) { + // These types are needed by g_type_from_name(), but may not be registered + // at this point. We need the g_type_class magic to make sure the compiler + // doesn't optimize away this code. + g_type_class_unref(g_type_class_ref(gtk_button_get_type())); + g_type_class_unref(g_type_class_ref(gtk_entry_get_type())); + g_type_class_unref(g_type_class_ref(gtk_frame_get_type())); + g_type_class_unref(g_type_class_ref(gtk_header_bar_get_type())); + g_type_class_unref(g_type_class_ref(gtk_image_get_type())); + g_type_class_unref(g_type_class_ref(gtk_info_bar_get_type())); + g_type_class_unref(g_type_class_ref(gtk_label_get_type())); + g_type_class_unref(g_type_class_ref(gtk_menu_get_type())); + g_type_class_unref(g_type_class_ref(gtk_menu_bar_get_type())); + g_type_class_unref(g_type_class_ref(gtk_menu_item_get_type())); + g_type_class_unref(g_type_class_ref(gtk_range_get_type())); + g_type_class_unref(g_type_class_ref(gtk_scrollbar_get_type())); + g_type_class_unref(g_type_class_ref(gtk_scrolled_window_get_type())); + g_type_class_unref(g_type_class_ref(gtk_separator_get_type())); + g_type_class_unref(g_type_class_ref(gtk_spinner_get_type())); + g_type_class_unref(g_type_class_ref(gtk_text_view_get_type())); + g_type_class_unref(g_type_class_ref(gtk_toggle_button_get_type())); + g_type_class_unref(g_type_class_ref(gtk_tree_view_get_type())); + g_type_class_unref(g_type_class_ref(gtk_window_get_type())); + g_type_class_unref(g_type_class_ref(gtk_combo_box_text_get_type())); + g_type_class_unref(g_type_class_ref(gtk_cell_view_get_type())); + g_type_class_unref(g_type_class_ref(gtk_scale_get_type())); + + // 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 combo = TakeGObject(gtk_combo_box_new_with_model(model)); + } + + ui::ColorProviderManager::Get().AppendColorProviderInitializer( + base::BindRepeating(AddGtkNativeCoreColorMixer)); OnThemeChanged(gtk_settings_get_default(), nullptr); } @@ -447,20 +125,34 @@ NativeThemeGtk::~NativeThemeGtk() { void NativeThemeGtk::SetThemeCssOverride(ScopedCssProvider provider) { if (theme_css_override_) { - gtk_style_context_remove_provider_for_screen( - gdk_screen_get_default(), - GTK_STYLE_PROVIDER(theme_css_override_.get())); + if (GtkCheckVersion(4)) { + gtk_style_context_remove_provider_for_display( + gdk_display_get_default(), + GTK_STYLE_PROVIDER(theme_css_override_.get())); + } else { + gtk_style_context_remove_provider_for_screen( + gdk_screen_get_default(), + GTK_STYLE_PROVIDER(theme_css_override_.get())); + } } theme_css_override_ = std::move(provider); if (theme_css_override_) { - gtk_style_context_add_provider_for_screen( - gdk_screen_get_default(), GTK_STYLE_PROVIDER(theme_css_override_.get()), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + if (GtkCheckVersion(4)) { + gtk_style_context_add_provider_for_display( + gdk_display_get_default(), + GTK_STYLE_PROVIDER(theme_css_override_.get()), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } else { + gtk_style_context_add_provider_for_screen( + gdk_screen_get_default(), + GTK_STYLE_PROVIDER(theme_css_override_.get()), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } } } -void NativeThemeGtk::NotifyObservers() { - NativeTheme::NotifyObservers(); +void NativeThemeGtk::NotifyOnNativeThemeUpdated() { + NativeTheme::NotifyOnNativeThemeUpdated(); // Update the preferred contrast settings for the NativeThemeAura instance and // notify its observers about the change. @@ -469,7 +161,7 @@ void NativeThemeGtk::NotifyObservers() { UserHasContrastPreference() ? ui::NativeThemeBase::PreferredContrast::kMore : ui::NativeThemeBase::PreferredContrast::kNoPreference); - native_theme->NotifyObservers(); + native_theme->NotifyOnNativeThemeUpdated(); } void NativeThemeGtk::OnThemeChanged(GtkSettings* settings, @@ -515,16 +207,27 @@ void NativeThemeGtk::OnThemeChanged(GtkSettings* settings, high_contrast ? ui::NativeThemeBase::PreferredContrast::kMore : ui::NativeThemeBase::PreferredContrast::kNoPreference); - NotifyObservers(); + NotifyOnNativeThemeUpdated(); } -SkColor NativeThemeGtk::GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const { +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; +} + +SkColor NativeThemeGtk::GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { base::Optional color = color_cache_[color_id]; if (!color) { - color = SkColorFromColorId(color_id, this, color_scheme); - if (!color) - color = ui::NativeThemeBase::GetSystemColor(color_id, color_scheme); + if (auto provider_color_id = ui::NativeThemeColorIdToColorId(color_id)) + color = SkColorFromColorId(provider_color_id.value()); + if (!color) { + color = ui::NativeThemeBase::GetSystemColorDeprecated( + color_id, color_scheme, apply_processing); + } color_cache_[color_id] = color; } DCHECK(color); @@ -538,31 +241,34 @@ void NativeThemeGtk::PaintArrowButton( State state, ColorScheme color_scheme, const ScrollbarArrowExtraParams& arrow) const { + // Add the "flat" styleclass to avoid drawing a border. auto context = GetStyleContextFromCss( GtkCheckVersion(3, 20) - ? "GtkScrollbar#scrollbar #contents GtkButton#button" - : "GtkRange.scrollbar.button"); + ? StrCat({kGtkCSSMenuScrollbar, " #range GtkButton#button.flat"}) + : "GtkRange.scrollbar.button.flat"); + // Remove any rounded corners since arrow scrollbar buttons are tiny. + ApplyCssToContext(context, "* { border-radius: 0px; }"); GtkStateFlags state_flags = StateToStateFlags(state); gtk_style_context_set_state(context, state_flags); switch (direction) { case kScrollbarUpArrow: - gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOP); + gtk_style_context_add_class(context, "top"); break; case kScrollbarRightArrow: - gtk_style_context_add_class(context, GTK_STYLE_CLASS_RIGHT); + gtk_style_context_add_class(context, "right"); break; case kScrollbarDownArrow: - gtk_style_context_add_class(context, GTK_STYLE_CLASS_BOTTOM); + gtk_style_context_add_class(context, "bottom"); break; case kScrollbarLeftArrow: - gtk_style_context_add_class(context, GTK_STYLE_CLASS_LEFT); + gtk_style_context_add_class(context, "left"); break; default: NOTREACHED(); } - PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true); + PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, false); PaintArrow(canvas, rect, direction, GetFgColorFromStyleContext(context)); } @@ -576,7 +282,7 @@ void NativeThemeGtk::PaintScrollbarTrack( PaintWidget( canvas, rect, GetStyleContextFromCss(GtkCheckVersion(3, 20) - ? "GtkScrollbar#scrollbar #contents #trough" + ? StrCat({kGtkCSSMenuScrollbar, " #trough"}) : "GtkScrollbar.scrollbar.trough"), BG_RENDER_NORMAL, true); } @@ -590,7 +296,7 @@ void NativeThemeGtk::PaintScrollbarThumb( ColorScheme color_scheme) const { auto context = GetStyleContextFromCss( GtkCheckVersion(3, 20) - ? "GtkScrollbar#scrollbar #contents #trough #slider" + ? StrCat({kGtkCSSMenuScrollbar, " #trough #slider"}) : "GtkScrollbar.scrollbar.slider"); gtk_style_context_set_state(context, StateToStateFlags(state)); PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true); @@ -612,8 +318,10 @@ void NativeThemeGtk::PaintMenuPopupBackground( const gfx::Size& size, const MenuBackgroundExtraParams& menu_background, ColorScheme color_scheme) const { - PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu"), - BG_RENDER_RECURSIVE, false); + auto context = GetStyleContextFromCss(kGtkCSSMenu); + // 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); } void NativeThemeGtk::PaintMenuItemBackground( @@ -622,7 +330,8 @@ void NativeThemeGtk::PaintMenuItemBackground( const gfx::Rect& rect, const MenuItemExtraParams& menu_item, ColorScheme color_scheme) const { - auto context = GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem"); + auto context = + GetStyleContextFromCss(StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem})); gtk_style_context_set_state(context, StateToStateFlags(state)); PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true); } @@ -656,43 +365,34 @@ void NativeThemeGtk::PaintMenuSeparator( }; if (GtkCheckVersion(3, 20)) { auto context = GetStyleContextFromCss( - "GtkMenu#menu GtkSeparator#separator.horizontal"); - GtkBorder margin, border, padding; + StrCat({kGtkCSSMenu, " GtkSeparator#separator.horizontal"})); int min_height = 1; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_margin(context, &margin); - gtk_style_context_get_border(context, &border); - gtk_style_context_get_padding(context, &padding); - gtk_style_context_get(context, "min-height", &min_height, nullptr); -#else - GtkStateFlags state = gtk_style_context_get_state(context); - gtk_style_context_get_margin(context, state, &margin); - gtk_style_context_get_border(context, state, &border); - gtk_style_context_get_padding(context, state, &padding); - gtk_style_context_get(context, state, "min-height", &min_height, nullptr); -#endif - int w = rect.width() - margin.left - margin.right; - int h = std::max( - min_height + padding.top + padding.bottom + border.top + border.bottom, - 1); - int x = margin.left; + auto margin = GtkStyleContextGetMargin(context); + auto border = GtkStyleContextGetBorder(context); + auto padding = GtkStyleContextGetPadding(context); + if (GtkCheckVersion(4)) + min_height = GetSeparatorSize(true).height(); + else + GtkStyleContextGet(context, "min-height", &min_height, nullptr); + int w = rect.width() - margin.left() - margin.right(); + int h = std::max(min_height + padding.top() + padding.bottom() + + border.top() + border.bottom(), + 1); + int x = margin.left(); int y = separator_offset(h); PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NORMAL, true); } else { -#if !GTK_CHECK_VERSION(3, 90, 0) auto context = GetStyleContextFromCss( - "GtkMenu#menu GtkMenuItem#menuitem.separator.horizontal"); + StrCat({kGtkCSSMenu, " ", kGtkCSSMenuItem, ".separator.horizontal"})); gboolean wide_separators = false; gint separator_height = 0; - gtk_style_context_get_style(context, "wide-separators", &wide_separators, - "separator-height", &separator_height, nullptr); + GtkStyleContextGetStyle(context, "wide-separators", &wide_separators, + "separator-height", &separator_height, nullptr); // This code was adapted from gtk/gtkmenuitem.c. For some reason, // padding is used as the margin. - GtkBorder padding; - gtk_style_context_get_padding(context, gtk_style_context_get_state(context), - &padding); - int w = rect.width() - padding.left - padding.right; - int x = rect.x() + padding.left; + auto padding = GtkStyleContextGetPadding(context); + int w = rect.width() - padding.left() - padding.right(); + int x = rect.x() + padding.left(); int h = wide_separators ? separator_height : 1; int y = rect.y() + separator_offset(h); if (wide_separators) { @@ -704,7 +404,6 @@ void NativeThemeGtk::PaintMenuSeparator( flags.setStrokeWidth(1); canvas->drawLine(x + 0.5f, y + 0.5f, x + w + 0.5f, y + 0.5f, flags); } -#endif } } diff --git a/chromium/ui/gtk/native_theme_gtk.h b/chromium/ui/gtk/native_theme_gtk.h index a89d1f78399..0d9366a3013 100644 --- a/chromium/ui/gtk/native_theme_gtk.h +++ b/chromium/ui/gtk/native_theme_gtk.h @@ -5,6 +5,8 @@ #ifndef UI_GTK_NATIVE_THEME_GTK_H_ #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" @@ -21,14 +23,11 @@ namespace gtk { using ScopedCssProvider = ScopedGObject; // A version of NativeTheme that uses GTK-rendered widgets. -class NativeThemeGtk : public ui::NativeThemeBase { +class COMPONENT_EXPORT(GTK) NativeThemeGtk : public ui::NativeThemeBase { public: static NativeThemeGtk* instance(); - // Overridden from ui::NativeThemeBase: - SkColor GetSystemColor( - ColorId color_id, - ColorScheme color_scheme = ColorScheme::kDefault) const override; + // ui::NativeThemeBase: void PaintArrowButton(cc::PaintCanvas* canvas, const gfx::Rect& rect, Part direction, @@ -71,10 +70,17 @@ class NativeThemeGtk : public ui::NativeThemeBase { const gfx::Rect& rect, const FrameTopAreaExtraParams& frame_top_area, ColorScheme color_scheme) const override; - void NotifyObservers() override; + void NotifyOnNativeThemeUpdated() override; void OnThemeChanged(GtkSettings* settings, GtkParamSpec* param); + protected: + // ui::NativeThemeBase: + bool AllowColorPipelineRedirection(ColorScheme color_scheme) const override; + SkColor GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const override; + private: friend class base::NoDestructor; diff --git a/chromium/ui/gtk/native_theme_gtk_unittest.cc b/chromium/ui/gtk/native_theme_gtk_unittest.cc new file mode 100644 index 00000000000..a19d79f564f --- /dev/null +++ b/chromium/ui/gtk/native_theme_gtk_unittest.cc @@ -0,0 +1,96 @@ +// 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/native_theme_gtk.h" + +#include + +#include "base/check.h" +#include "base/command_line.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/native_theme/native_theme_color_id.h" +#include "ui/native_theme/test/color_utils.h" + +namespace gtk { + +namespace { + +class NativeThemeGtkRedirectedEquivalenceTest + : public testing::TestWithParam< + std::tuple> { + public: + NativeThemeGtkRedirectedEquivalenceTest() { + static bool loaded = LoadGtk(BUILDFLAG(GTK_VERSION)); + CHECK(loaded); + GtkInitFromCommandLine(base::CommandLine(base::CommandLine::NO_PROGRAM)); + } + + static std::string ParamInfoToString( + ::testing::TestParamInfo< + std::tuple> + param_info) { + auto param_tuple = param_info.param; + return ColorSchemeToString( + std::get(param_tuple)) + + "_With_" + + ui::test::ColorIdToString( + std::get(param_tuple)); + } + + private: + static std::string ColorSchemeToString(ui::NativeTheme::ColorScheme scheme) { + switch (scheme) { + case ui::NativeTheme::ColorScheme::kDefault: + NOTREACHED() + << "Cannot unit test kDefault as it depends on machine state."; + return "InvalidColorScheme"; + case ui::NativeTheme::ColorScheme::kLight: + return "kLight"; + case ui::NativeTheme::ColorScheme::kDark: + return "kDark"; + case ui::NativeTheme::ColorScheme::kPlatformHighContrast: + return "kPlatformHighContrast"; + } + } +}; + +} // namespace + +TEST_P(NativeThemeGtkRedirectedEquivalenceTest, GetSystemColor) { + auto param_tuple = GetParam(); + auto color_scheme = std::get(param_tuple); + auto color_id = std::get(param_tuple); + + // Verifies that colors with and without the Color Provider are the same. + auto* native_theme_gtk = NativeThemeGtk::instance(); + + ui::test::PrintableSkColor original{ + native_theme_gtk->GetSystemColor(color_id, color_scheme)}; + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kColorProviderRedirection); + ui::test::PrintableSkColor redirected{ + native_theme_gtk->GetSystemColor(color_id, color_scheme)}; + + EXPECT_EQ(original, redirected); +} + +#define OP(enum_name) ui::NativeTheme::ColorId::enum_name +INSTANTIATE_TEST_SUITE_P( + , + NativeThemeGtkRedirectedEquivalenceTest, + ::testing::Combine( + ::testing::Values(ui::NativeTheme::ColorScheme::kLight, + ui::NativeTheme::ColorScheme::kDark, + ui::NativeTheme::ColorScheme::kPlatformHighContrast), + ::testing::Values(NATIVE_THEME_COLOR_IDS)), + NativeThemeGtkRedirectedEquivalenceTest::ParamInfoToString); +#undef OP + +} // namespace gtk diff --git a/chromium/ui/gtk/nav_button_provider_gtk.cc b/chromium/ui/gtk/nav_button_provider_gtk.cc index 119da0ead30..085febcdeac 100644 --- a/chromium/ui/gtk/nav_button_provider_gtk.cc +++ b/chromium/ui/gtk/nav_button_provider_gtk.cc @@ -6,9 +6,12 @@ #include +#include "base/notreached.h" +#include "ui/base/glib/glib_cast.h" #include "ui/base/glib/scoped_gobject.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_source.h" +#include "ui/gtk/gtk_compat.h" #include "ui/gtk/gtk_util.h" #include "ui/views/widget/widget.h" @@ -16,11 +19,13 @@ namespace gtk { namespace { -#if GTK_CHECK_VERSION(3, 90, 0) -using NavButtonIcon = ScopedGObject; -#else -using NavButtonIcon = ScopedGObject; -#endif +struct NavButtonIcon { + // Used on Gtk3. + ScopedGObject pixbuf; + + // Used on Gtk4. + ScopedGObject texture; +}; // gtkheaderbar.c uses GTK_ICON_SIZE_MENU, which is 16px. const int kNavButtonIconSize = 16; @@ -78,110 +83,109 @@ const char* IconNameFromButtonType( } } -gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) { - return gfx::Insets(border.top, border.left, border.bottom, border.right); -} - -gfx::Insets PaddingFromStyleContext(GtkStyleContext* context, - GtkStateFlags state) { - GtkBorder padding; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_padding(context, &padding); -#else - gtk_style_context_get_padding(context, state, &padding); -#endif - return InsetsFromGtkBorder(padding); -} - -gfx::Insets BorderFromStyleContext(GtkStyleContext* context, - GtkStateFlags state) { - GtkBorder border; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_border(context, &border); -#else - gtk_style_context_get_border(context, state, &border); -#endif - return InsetsFromGtkBorder(border); -} - -gfx::Insets MarginFromStyleContext(GtkStyleContext* context, - GtkStateFlags state) { - GtkBorder margin; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_margin(context, &margin); -#else - gtk_style_context_get_margin(context, state, &margin); -#endif - return InsetsFromGtkBorder(margin); -} - gfx::Size LoadNavButtonIcon( views::NavButtonProvider::FrameButtonDisplayType type, GtkStyleContext* button_context, int scale, NavButtonIcon* icon = nullptr) { const char* icon_name = IconNameFromButtonType(type); -#if GTK_CHECK_VERSION(3, 90, 0) - ScopedGObject icon_paintable(gtk_icon_theme_lookup_icon( + if (!GtkCheckVersion(4)) { + auto icon_info = TakeGObject(gtk_icon_theme_lookup_icon_for_scale( + GetDefaultIconTheme(), icon_name, kNavButtonIconSize, scale, + static_cast(GTK_ICON_LOOKUP_USE_BUILTIN | + GTK_ICON_LOOKUP_GENERIC_FALLBACK))); + auto icon_pixbuf = TakeGObject(gtk_icon_info_load_symbolic_for_context( + icon_info, button_context, nullptr, nullptr)); + gfx::Size size{gdk_pixbuf_get_width(icon_pixbuf), + gdk_pixbuf_get_height(icon_pixbuf)}; + if (icon) + icon->pixbuf = std::move(icon_pixbuf); + return size; + } + auto icon_paintable = Gtk4IconThemeLookupIcon( GetDefaultIconTheme(), icon_name, nullptr, kNavButtonIconSize, scale, - GTK_TEXT_DIR_NONE, static_cast(0))); - auto* paintable = GDK_PAINTABLE(icon_paintable); - int width = gdk_paintable_get_intrinsic_width(paintable); - int height = gdk_paintable_get_intrinsic_height(paintable); + GTK_TEXT_DIR_NONE, static_cast(0)); + auto* paintable = + GlibCast(icon_paintable.get(), gdk_paintable_get_type()); + int width = scale * gdk_paintable_get_intrinsic_width(paintable); + int height = scale * gdk_paintable_get_intrinsic_height(paintable); if (icon) { auto* snapshot = gtk_snapshot_new(); gdk_paintable_snapshot(paintable, snapshot, width, height); - ScopedGObject node(gtk_snapshot_free_to_node(snapshot)); - auto rect = GRAPHENE_RECT_INIT(0, 0, width, height); - ScopedGObject renderer(gsk_cairo_renderer_new()); - *icon = NavButtonIcon(gsk_renderer_render_texture(renderer, node, &rect)); + auto* node = gtk_snapshot_free_to_node(snapshot); + GdkTexture* texture = GetTextureFromRenderNode(node); + size_t nbytes = width * height * sizeof(SkColor); + SkColor* pixels = reinterpret_cast(g_malloc(nbytes)); + size_t stride = sizeof(SkColor) * width; + gdk_texture_download(texture, reinterpret_cast(pixels), stride); + SkColor fg = GetFgColorFromStyleContext(button_context); + for (int i = 0; i < width * height; ++i) + pixels[i] = SkColorSetA(fg, SkColorGetA(pixels[i])); + icon->texture = TakeGObject( + gdk_memory_texture_new(width, height, GDK_MEMORY_B8G8R8A8, + g_bytes_new_take(pixels, nbytes), stride)); + gsk_render_node_unref(node); } return {width, height}; -#else - ScopedGObject icon_info(gtk_icon_theme_lookup_icon_for_scale( - GetDefaultIconTheme(), icon_name, kNavButtonIconSize, scale, - static_cast(GTK_ICON_LOOKUP_USE_BUILTIN | - GTK_ICON_LOOKUP_GENERIC_FALLBACK))); - NavButtonIcon icon_pixbuf(gtk_icon_info_load_symbolic_for_context( - icon_info, button_context, nullptr, nullptr)); - gfx::Size size{gdk_pixbuf_get_width(icon_pixbuf), - gdk_pixbuf_get_height(icon_pixbuf)}; - if (icon) - *icon = std::move(icon_pixbuf); - return size; -#endif } gfx::Size GetMinimumWidgetSize(gfx::Size content_size, GtkStyleContext* content_context, - GtkStyleContext* widget_context, - GtkStateFlags state) { + GtkCssContext widget_context) { gfx::Rect widget_rect = gfx::Rect(content_size); if (content_context) - widget_rect.Inset(-MarginFromStyleContext(content_context, state)); -#if !GTK_CHECK_VERSION(3, 90, 0) - if (GtkCheckVersion(3, 20)) { - int min_width, min_height; - gtk_style_context_get(widget_context, state, "min-width", &min_width, - "min-height", &min_height, nullptr); + widget_rect.Inset(-GtkStyleContextGetMargin(content_context)); + + int min_width = 0; + int min_height = 0; + // On GTK3, get the min size from the CSS directly. + if (GtkCheckVersion(3, 20) && !GtkCheckVersion(4)) { + GtkStyleContextGet(widget_context, "min-width", &min_width, "min-height", + &min_height, nullptr); + widget_rect.set_width(std::max(widget_rect.width(), min_width)); + widget_rect.set_height(std::max(widget_rect.height(), min_height)); + } + + widget_rect.Inset(-GtkStyleContextGetPadding(widget_context)); + widget_rect.Inset(-GtkStyleContextGetBorder(widget_context)); + + // On GTK4, the CSS properties are hidden, so compute the min size indirectly, + // which will include the border, margin, and padding. We can't take this + // codepath on GTK3 since we only have a widget available in GTK4. + if (GtkCheckVersion(4)) { + gtk_widget_measure(widget_context.widget(), GTK_ORIENTATION_HORIZONTAL, -1, + &min_width, nullptr, nullptr, nullptr); + gtk_widget_measure(widget_context.widget(), GTK_ORIENTATION_VERTICAL, -1, + &min_height, nullptr, nullptr, nullptr); + + // The returned "minimum size" is the drawn size of the widget, which + // doesn't include the margin. However, GTK includes this size in its + // calculation. So remove the margin, recompute the min size, then add it + // back. + auto margin = GtkStyleContextGetMargin(widget_context); + widget_rect.Inset(-margin); widget_rect.set_width(std::max(widget_rect.width(), min_width)); widget_rect.set_height(std::max(widget_rect.height(), min_height)); + widget_rect.Inset(margin); } -#endif - widget_rect.Inset(-PaddingFromStyleContext(widget_context, state)); - widget_rect.Inset(-BorderFromStyleContext(widget_context, state)); + return widget_rect.size(); } -ScopedStyleContext CreateHeaderContext(bool maximized) { - std::string window_selector = "GtkWindow#window.background"; +GtkCssContext CreateHeaderContext(bool maximized) { + std::string window_selector = "GtkWindow#window.background.csd"; if (maximized) window_selector += ".maximized"; return AppendCssNodeToStyleContext( - AppendCssNodeToStyleContext(nullptr, window_selector), + AppendCssNodeToStyleContext({}, window_selector), "GtkHeaderBar#headerbar.header-bar.titlebar"); } +GtkCssContext CreateWindowControlsContext(bool maximized) { + return AppendCssNodeToStyleContext(CreateHeaderContext(maximized), + "#windowcontrols"); +} + void CalculateUnscaledButtonSize( views::NavButtonProvider::FrameButtonDisplayType type, bool maximized, @@ -192,7 +196,7 @@ void CalculateUnscaledButtonSize( // button for each state. For this reason, render buttons for all // states at the size of a GTK_STATE_FLAG_NORMAL button. auto button_context = AppendCssNodeToStyleContext( - CreateHeaderContext(maximized), + CreateWindowControlsContext(maximized), "GtkButton#button.titlebutton." + std::string(ButtonStyleClassFromButtonType(type))); @@ -200,13 +204,12 @@ void CalculateUnscaledButtonSize( auto image_context = AppendCssNodeToStyleContext(button_context, "GtkImage#image"); - gfx::Size image_size = GetMinimumWidgetSize(icon_size, nullptr, image_context, - GTK_STATE_FLAG_NORMAL); + gfx::Size image_size = + GetMinimumWidgetSize(icon_size, nullptr, image_context); - *button_size = GetMinimumWidgetSize(image_size, image_context, button_context, - GTK_STATE_FLAG_NORMAL); - *button_margin = - MarginFromStyleContext(button_context, GTK_STATE_FLAG_NORMAL); + *button_size = + GetMinimumWidgetSize(image_size, image_context, button_context); + *button_margin = GtkStyleContextGetMargin(button_context); } class NavButtonImageSource : public gfx::ImageSkiaSource { @@ -232,8 +235,9 @@ class NavButtonImageSource : public gfx::ImageSkiaSource { if (button_size_.IsEmpty()) return gfx::ImageSkiaRep(); - auto button_context = AppendCssNodeToStyleContext( - CreateHeaderContext(maximized_), "GtkButton#button.titlebutton"); + auto button_context = + AppendCssNodeToStyleContext(CreateWindowControlsContext(maximized_), + "GtkButton#button.titlebutton"); gtk_style_context_add_class(button_context, ButtonStyleClassFromButtonType(type_)); GtkStateFlags button_state = GtkStateFlagsFromButtonState(state_); @@ -257,27 +261,39 @@ class NavButtonImageSource : public gfx::ImageSkiaSource { // be downsized when it would have clipped. In GTK, the image is always // scaled to fit the drawing region (preserving aspect ratio). Only add // "contain" if clipping would occur. - cairo_pattern_t* cr_pattern = nullptr; - cairo_surface_t* cr_surface = nullptr; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get(button_context, GTK_STYLE_PROPERTY_BACKGROUND_IMAGE, - &cr_pattern, nullptr); -#else - gtk_style_context_get(button_context, button_state, - GTK_STYLE_PROPERTY_BACKGROUND_IMAGE, &cr_pattern, - nullptr); -#endif - if (cr_pattern && - cairo_pattern_get_surface(cr_pattern, &cr_surface) == - CAIRO_STATUS_SUCCESS && - cr_surface && - cairo_surface_get_type(cr_surface) == CAIRO_SURFACE_TYPE_IMAGE && - (cairo_image_surface_get_width(cr_surface) > button_size_.width() || - cairo_image_surface_get_height(cr_surface) > button_size_.height())) { + int bg_width = 0; + int bg_height = 0; + if (GtkCheckVersion(4)) { + auto* snapshot = gtk_snapshot_new(); + gtk_snapshot_render_background(snapshot, button_context, 0, 0, + button_size_.width(), + button_size_.height()); + if (auto* node = gtk_snapshot_free_to_node(snapshot)) { + if (GdkTexture* texture = GetTextureFromRenderNode(node)) { + bg_width = gdk_texture_get_width(texture); + bg_height = gdk_texture_get_height(texture); + } + gsk_render_node_unref(node); + } + } else { + cairo_pattern_t* cr_pattern = nullptr; + cairo_surface_t* cr_surface = nullptr; + GtkStyleContextGet(button_context, GTK_STYLE_PROPERTY_BACKGROUND_IMAGE, + &cr_pattern, nullptr); + if (cr_pattern) { + cairo_pattern_get_surface(cr_pattern, &cr_surface); + if (cr_surface && + cairo_surface_get_type(cr_surface) == CAIRO_SURFACE_TYPE_IMAGE) { + bg_width = cairo_image_surface_get_width(cr_surface); + bg_height = cairo_image_surface_get_height(cr_surface); + } + cairo_pattern_destroy(cr_pattern); + } + } + if (bg_width > button_size_.width() || bg_height > button_size_.height()) { ApplyCssToContext(button_context, ".titlebutton { background-size: contain; }"); } - cairo_pattern_destroy(cr_pattern); // Gtk doesn't support fractional scale factors, but chrome does. // Rendering the button background and border at a fractional @@ -285,9 +301,9 @@ class NavButtonImageSource : public gfx::ImageSkiaSource { // transform. But the icon is loaded from a pixbuf, so we pick // the next-highest integer scale and manually downsize. int pixbuf_scale = scale == static_cast(scale) ? scale : scale + 1; - NavButtonIcon icon_pixbuf; + NavButtonIcon icon; auto icon_size = - LoadNavButtonIcon(type_, button_context, pixbuf_scale, &icon_pixbuf); + LoadNavButtonIcon(type_, button_context, pixbuf_scale, &icon); SkBitmap bitmap; bitmap.allocN32Pixels(scale * button_size_.width(), @@ -310,8 +326,8 @@ class NavButtonImageSource : public gfx::ImageSkiaSource { cairo_save(cr); float pixbuf_extra_scale = scale / pixbuf_scale; cairo_scale(cr, pixbuf_extra_scale, pixbuf_extra_scale); - gtk_render_icon( - button_context, cr, icon_pixbuf, + GtkRenderIcon( + button_context, cr, icon.pixbuf, icon.texture, ((pixbuf_scale * button_size_.width() - icon_size.width()) / 2), ((pixbuf_scale * button_size_.height() - icon_size.height()) / 2)); cairo_restore(cr); @@ -339,14 +355,7 @@ void NavButtonProviderGtk::RedrawImages(int top_area_height, bool maximized, bool active) { auto header_context = CreateHeaderContext(maximized); - - GtkBorder header_padding; -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_style_context_get_padding(header_context, &header_padding); -#else - gtk_style_context_get_padding(header_context, GTK_STATE_FLAG_NORMAL, - &header_padding); -#endif + auto header_padding = GtkStyleContextGetPadding(header_context); double scale = 1.0f; std::map @@ -366,20 +375,18 @@ void NavButtonProviderGtk::RedrawImages(int top_area_height, button_margins[type].top() + button_margins[type].bottom(); - int needed_height = header_padding.top + button_unconstrained_height + - header_padding.bottom; + int needed_height = header_padding.top() + button_unconstrained_height + + header_padding.bottom(); if (needed_height > top_area_height) scale = std::min(scale, static_cast(top_area_height) / needed_height); } - top_area_spacing_ = InsetsFromGtkBorder(header_padding); - top_area_spacing_ = - gfx::Insets(std::round(scale * top_area_spacing_.top()), - std::round(scale * top_area_spacing_.left()), - std::round(scale * top_area_spacing_.bottom()), - std::round(scale * top_area_spacing_.right())); + top_area_spacing_ = gfx::Insets(std::round(scale * header_padding.top()), + std::round(scale * header_padding.left()), + std::round(scale * header_padding.bottom()), + std::round(scale * header_padding.right())); inter_button_spacing_ = std::round(scale * kHeaderSpacing); @@ -388,7 +395,8 @@ void NavButtonProviderGtk::RedrawImages(int top_area_height, scale * (button_sizes[type].height() + button_margins[type].top() + button_margins[type].bottom()); double available_height = - top_area_height - scale * (header_padding.top + header_padding.bottom); + top_area_height - + scale * (header_padding.top() + header_padding.bottom()); double scaled_button_offset = (available_height - button_height) / 2; gfx::Size size = button_sizes[type]; @@ -396,7 +404,7 @@ void NavButtonProviderGtk::RedrawImages(int top_area_height, std::round(scale * size.height())); gfx::Insets margin = button_margins[type]; margin = - gfx::Insets(std::round(scale * (header_padding.top + margin.top()) + + gfx::Insets(std::round(scale * (header_padding.top() + margin.top()) + scaled_button_offset), std::round(scale * margin.left()), 0, std::round(scale * margin.right())); diff --git a/chromium/ui/gtk/printing/print_dialog_gtk.cc b/chromium/ui/gtk/printing/print_dialog_gtk.cc index f2ed36e1258..7363dc20823 100644 --- a/chromium/ui/gtk/printing/print_dialog_gtk.cc +++ b/chromium/ui/gtk/printing/print_dialog_gtk.cc @@ -192,7 +192,7 @@ PrintDialogGtk::~PrintDialogGtk() { parent->RemoveObserver(this); gtk::ClearAuraTransientParent(dialog_, parent); } - gtk_widget_destroy(dialog_); + gtk::GtkWindowDestroy(dialog_); dialog_ = nullptr; } if (gtk_settings_) { @@ -371,8 +371,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 // Handle the case when the existing |gtk_settings_| has "selection" selected // as the page range, but |has_selection| is false. @@ -408,7 +412,7 @@ void PrintDialogGtk::ShowDialog( } void PrintDialogGtk::PrintDocument(const printing::MetafilePlayer& metafile, - const base::string16& document_name) { + const std::u16string& document_name) { // This runs on the print worker thread, does not block the UI thread. DCHECK(!owning_task_runner()->RunsTasksInCurrentSequence()); @@ -533,7 +537,7 @@ static void OnJobCompletedThunk(GtkPrintJob* print_job, static_cast(user_data)->OnJobCompleted(print_job, error); } void PrintDialogGtk::SendDocumentToPrinter( - const base::string16& document_name) { + const std::u16string& document_name) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); // If |printer_| is nullptr then somehow the GTK printer list changed out diff --git a/chromium/ui/gtk/printing/print_dialog_gtk.h b/chromium/ui/gtk/printing/print_dialog_gtk.h index f065848a163..6eba9d4a192 100644 --- a/chromium/ui/gtk/printing/print_dialog_gtk.h +++ b/chromium/ui/gtk/printing/print_dialog_gtk.h @@ -43,7 +43,7 @@ class PrintDialogGtk : public printing::PrintDialogGtkInterface, bool has_selection, PrintingContextLinux::PrintSettingsCallback callback) override; void PrintDocument(const printing::MetafilePlayer& metafile, - const base::string16& document_name) override; + const std::u16string& document_name) override; void AddRefToDialog() override; void ReleaseDialog() override; @@ -61,7 +61,7 @@ class PrintDialogGtk : public printing::PrintDialogGtkInterface, CHROMEG_CALLBACK_1(PrintDialogGtk, void, OnResponse, GtkWidget*, int); // Prints document named |document_name|. - void SendDocumentToPrinter(const base::string16& document_name); + void SendDocumentToPrinter(const std::u16string& document_name); // Helper function for initializing |context_|'s PrintSettings with a given // |settings|. diff --git a/chromium/ui/gtk/printing/printing_gtk_util.cc b/chromium/ui/gtk/printing/printing_gtk_util.cc index dc922bf31c6..0b7d8010cef 100644 --- a/chromium/ui/gtk/printing/printing_gtk_util.cc +++ b/chromium/ui/gtk/printing/printing_gtk_util.cc @@ -7,7 +7,8 @@ #include #include -#include "base/strings/string16.h" +#include + #include "base/strings/utf_string_conversions.h" #include "printing/print_settings.h" #include "printing/printing_context_linux.h" @@ -48,8 +49,8 @@ void InitPrintSettingsGtk(GtkPrintSettings* settings, DCHECK(print_settings); const char* printer_name = gtk_print_settings_get_printer(settings); - base::string16 name = - printer_name ? base::UTF8ToUTF16(printer_name) : base::string16(); + std::u16string name = + printer_name ? base::UTF8ToUTF16(printer_name) : std::u16string(); print_settings->set_device_name(name); gfx::Size physical_size_device_units; diff --git a/chromium/ui/gtk/select_file_dialog_impl.h b/chromium/ui/gtk/select_file_dialog_impl.h index 3cb8ee5d6a9..e4698a945b7 100644 --- a/chromium/ui/gtk/select_file_dialog_impl.h +++ b/chromium/ui/gtk/select_file_dialog_impl.h @@ -55,7 +55,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog { // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/gtk/select_file_dialog_impl_gtk.cc b/chromium/ui/gtk/select_file_dialog_impl_gtk.cc index 1d7b74b1644..ead63d10c5d 100644 --- a/chromium/ui/gtk/select_file_dialog_impl_gtk.cc +++ b/chromium/ui/gtk/select_file_dialog_impl_gtk.cc @@ -4,6 +4,7 @@ #include "ui/gtk/select_file_dialog_impl_gtk.h" +#include #include #include #include @@ -17,6 +18,8 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/no_destructor.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -25,6 +28,7 @@ #include "ui/aura/window_observer.h" #include "ui/base/glib/scoped_gobject.h" #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_util.h" @@ -33,24 +37,42 @@ #include "ui/strings/grit/ui_strings.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h" +namespace gtk { + namespace { -#if GTK_CHECK_VERSION(3, 90, 0) -// GTK stock items have been deprecated. The docs say to switch to using the -// strings "_Open", etc. However this breaks i18n. We could supply our own -// internationalized strings, but the "_" in these strings is significant: it's -// the keyboard shortcut to select these actions. TODO(thomasanderson): Provide -// internationalized strings when GTK provides support for it. -const char kCancelLabel[] = "_Cancel"; -const char kOpenLabel[] = "_Open"; -const char kSaveLabel[] = "_Save"; -#else -G_GNUC_BEGIN_IGNORE_DEPRECATIONS -const char* const kCancelLabel = GTK_STOCK_CANCEL; -const char* const kOpenLabel = GTK_STOCK_OPEN; -const char* const kSaveLabel = GTK_STOCK_SAVE; -G_GNUC_END_IGNORE_DEPRECATIONS -#endif +// TODO(https://crbug.com/981309): These getters will be unnecessary after +// migrating to GtkFileChooserNative. +const char* GettextPackage() { + static base::NoDestructor gettext_package( + "gtk" + base::NumberToString(GtkVersion().components()[0]) + "0"); + return gettext_package->c_str(); +} + +const char* GtkGettext(const char* str) { + return g_dgettext(GettextPackage(), str); +} + +const char* GetCancelLabel() { + if (!GtkCheckVersion(4)) + return "gtk-cancel"; // In GTK3, this is GTK_STOCK_CANCEL. + static const char* cancel = GtkGettext("_Cancel"); + return cancel; +} + +const char* GetOpenLabel() { + if (!GtkCheckVersion(4)) + return "gtk-open"; // In GTK3, this is GTK_STOCK_OPEN. + static const char* open = GtkGettext("_Open"); + return open; +} + +const char* GetSaveLabel() { + if (!GtkCheckVersion(4)) + return "gtk-save"; // In GTK3, this is GTK_STOCK_SAVE. + static const char* save = GtkGettext("_Save"); + return save; +} // Runs DesktopWindowTreeHostLinux::EnableEventListening() when the file-picker // is closed. @@ -59,109 +81,88 @@ void OnFilePickerDestroy(base::OnceClosure* callback_raw) { std::move(*callback).Run(); } -void GtkFileChooserSetCurrentFolder(GtkFileChooser* dialog, - const base::FilePath& path) { -#if GTK_CHECK_VERSION(3, 90, 0) - ScopedGObject file(g_file_new_for_path(path.value().c_str())); - gtk_file_chooser_set_current_folder(dialog, file, nullptr); -#else - gtk_file_chooser_set_current_folder(dialog, path.value().c_str()); -#endif -} - void GtkFileChooserSetFilename(GtkFileChooser* dialog, const base::FilePath& path) { -#if GTK_CHECK_VERSION(3, 90, 0) - ScopedGObject file(g_file_new_for_path(path.value().c_str())); - gtk_file_chooser_set_file(dialog, file, nullptr); -#else - gtk_file_chooser_set_filename(dialog, path.value().c_str()); -#endif -} - -void GtkWindowDestroy(GtkWidget* widget) { -#if GTK_CHECK_VERSION(3, 90, 0) - gtk_window_destroy(GTK_WINDOW(widget)); -#else - gtk_widget_destroy(widget); -#endif + if (GtkCheckVersion(4)) { + auto file = TakeGObject(g_file_new_for_path(path.value().c_str())); + gtk_file_chooser_set_file(dialog, file, nullptr); + } else { + gtk_file_chooser_set_filename(dialog, path.value().c_str()); + } } int GtkDialogSelectedFilterIndex(GtkWidget* dialog) { GtkFileFilter* selected_filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); -#if GTK_CHECK_VERSION(3, 90, 0) - ScopedGObject filters( - gtk_file_chooser_get_filters(GTK_FILE_CHOOSER(dialog))); - int size = g_list_model_get_n_items(filters); int idx = -1; - for (; idx < size; ++idx) { - if (g_list_model_get_item(filters, idx) == selected_filter) - break; + if (GtkCheckVersion(4)) { + auto filters = + TakeGObject(gtk_file_chooser_get_filters(GTK_FILE_CHOOSER(dialog))); + int size = g_list_model_get_n_items(filters); + for (; idx < size; ++idx) { + if (g_list_model_get_item(filters, idx) == selected_filter) + break; + } + } else { + GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); + idx = g_slist_index(filters, selected_filter); + g_slist_free(filters); } -#else - GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); - int idx = g_slist_index(filters, selected_filter); - g_slist_free(filters); -#endif return idx; } std::string GtkFileChooserGetFilename(GtkWidget* dialog) { const char* filename = nullptr; -#if GTK_CHECK_VERSION(3, 90, 0) - ScopedGObject file( - gtk_file_chooser_get_file(GTK_FILE_CHOOSER(dialog))); - if (file) - filename = g_file_peek_path(file); -#else struct GFreeDeleter { void operator()(gchar* ptr) const { g_free(ptr); } }; - std::unique_ptr gchar_filename( - gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); - filename = gchar_filename.get(); -#endif + std::unique_ptr gchar_filename; + if (GtkCheckVersion(4)) { + if (auto file = + TakeGObject(gtk_file_chooser_get_file(GTK_FILE_CHOOSER(dialog)))) { + filename = g_file_peek_path(file); + } + } else { + gchar_filename = std::unique_ptr( + gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); + filename = gchar_filename.get(); + } return filename ? std::string(filename) : std::string(); } std::vector GtkFileChooserGetFilenames(GtkWidget* dialog) { std::vector filenames_fp; -#if GTK_CHECK_VERSION(3, 90, 0) - ScopedGObject files( - gtk_file_chooser_get_files(GTK_FILE_CHOOSER(dialog))); - auto size = g_list_model_get_n_items(files); - for (unsigned int i = 0; i < size; ++i) { - ScopedGObject file(G_FILE(g_list_model_get_object(files, i))); - filenames_fp.emplace_back(g_file_peek_path(file)); - } -#else - GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - if (!filenames) - return {}; - for (GSList* iter = filenames; iter != nullptr; iter = g_slist_next(iter)) { - base::FilePath path(static_cast(iter->data)); - g_free(iter->data); - filenames_fp.push_back(path); + if (GtkCheckVersion(4)) { + auto files = Gtk4FileChooserGetFiles(GTK_FILE_CHOOSER(dialog)); + auto size = g_list_model_get_n_items(files); + for (unsigned int i = 0; i < size; ++i) { + auto file = TakeGObject(G_FILE(g_list_model_get_object(files, i))); + filenames_fp.emplace_back(g_file_peek_path(file)); + } + } else { + GSList* filenames = + gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + if (!filenames) + return {}; + for (GSList* iter = filenames; iter != nullptr; iter = g_slist_next(iter)) { + base::FilePath path(static_cast(iter->data)); + g_free(iter->data); + filenames_fp.push_back(path); + } + g_slist_free(filenames); } - g_slist_free(filenames); -#endif return filenames_fp; } } // namespace -namespace gtk { - -#if !GTK_CHECK_VERSION(3, 90, 0) // The size of the preview we display for selected image files. We set height // larger than width because generally there is more free space vertically -// than horiztonally (setting the preview image will alway expand the width of +// than horiztonally (setting the preview image will always expand the width of // the dialog, but usually not the height). The image's aspect ratio will always -// be preserved. +// be preserved. Only used on GTK3. static const int kPreviewWidth = 256; static const int kPreviewHeight = 512; -#endif SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplGTK( Listener* listener, @@ -177,9 +178,13 @@ SelectFileDialogImplGTK::SelectFileDialogImplGTK( SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { for (auto* window : parents_) window->RemoveObserver(this); - while (!dialogs_.empty()) { - auto* widget = *(dialogs_.begin()); - GtkWindowDestroy(widget); + auto dialogs = dialogs_; + for (auto dialog_signal : dialogs) { + auto* dialog = dialog_signal.first; + auto signal_id = dialog_signal.second; + g_signal_handler_disconnect(dialog, signal_id); + GtkWindowDestroy(dialog); + OnFileChooserDestroy(dialog); } } @@ -193,7 +198,8 @@ bool SelectFileDialogImplGTK::HasMultipleFileTypeChoicesImpl() { void SelectFileDialogImplGTK::OnWindowDestroying(aura::Window* window) { // Remove the |parent| property associated with the |dialog|. - for (auto* dialog : dialogs_) { + for (auto dialog_signal : dialogs_) { + auto* dialog = dialog_signal.first; aura::Window* parent = GetAuraTransientParent(dialog); if (parent == window) ClearAuraTransientParent(dialog, parent); @@ -209,7 +215,7 @@ void SelectFileDialogImplGTK::OnWindowDestroying(aura::Window* window) { // We ignore |default_extension|. void SelectFileDialogImplGTK::SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -250,23 +256,22 @@ void SelectFileDialogImplGTK::SelectFileImpl( NOTREACHED(); return; } -#if GTK_CHECK_VERSION(3, 90, 0) - 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 - dialogs_.insert(dialog); - - g_signal_connect(dialog, "destroy", G_CALLBACK(OnFileChooserDestroyThunk), - this); - -#if !GTK_CHECK_VERSION(3, 90, 0) - preview_ = gtk_image_new(); - g_signal_connect(dialog, "update-preview", G_CALLBACK(OnUpdatePreviewThunk), - this); - gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); -#endif + if (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); + } + + dialogs_[dialog] = g_signal_connect( + dialog, "destroy", G_CALLBACK(OnFileChooserDestroyThunk), this); + + if (!GtkCheckVersion(4)) { + preview_ = gtk_image_new(); + g_signal_connect(dialog, "update-preview", G_CALLBACK(OnUpdatePreviewThunk), + this); + gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); + } params_map_[dialog] = params; @@ -292,9 +297,8 @@ void SelectFileDialogImplGTK::SelectFileImpl( } } -#if !GTK_CHECK_VERSION(3, 90, 0) - gtk_widget_show_all(dialog); -#endif + if (!GtkCheckVersion(4)) + gtk_widget_show_all(dialog); gtk::GtkUi::GetDelegate()->ShowGtkWindow(GTK_WINDOW(dialog)); } @@ -392,8 +396,8 @@ GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( const base::FilePath& default_path, gfx::NativeWindow parent) { GtkWidget* dialog = gtk_file_chooser_dialog_new( - title.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, kCancelLabel, - GTK_RESPONSE_CANCEL, kOpenLabel, GTK_RESPONSE_ACCEPT, nullptr); + title.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, GetCancelLabel(), + GTK_RESPONSE_CANCEL, GetOpenLabel(), GTK_RESPONSE_ACCEPT, nullptr); SetGtkTransientForAura(dialog, parent); AddFilters(GTK_FILE_CHOOSER(dialog)); @@ -428,11 +432,11 @@ GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( (type == SELECT_UPLOAD_FOLDER) ? l10n_util::GetStringUTF8( IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON) - : kOpenLabel; + : GetOpenLabel(); GtkWidget* dialog = gtk_file_chooser_dialog_new( title_string.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - kCancelLabel, GTK_RESPONSE_CANCEL, accept_button_label.c_str(), + GetCancelLabel(), GTK_RESPONSE_CANCEL, accept_button_label.c_str(), GTK_RESPONSE_ACCEPT, nullptr); SetGtkTransientForAura(dialog, parent); GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog); @@ -495,8 +499,9 @@ GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog( : l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); GtkWidget* dialog = gtk_file_chooser_dialog_new( - title_string.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_SAVE, kCancelLabel, - GTK_RESPONSE_CANCEL, kSaveLabel, GTK_RESPONSE_ACCEPT, nullptr); + title_string.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_SAVE, + GetCancelLabel(), GTK_RESPONSE_CANCEL, GetSaveLabel(), + GTK_RESPONSE_ACCEPT, nullptr); SetGtkTransientForAura(dialog, parent); AddFilters(GTK_FILE_CHOOSER(dialog)); @@ -519,10 +524,10 @@ GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog( } gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); // Overwrite confirmation is always enabled in GTK4. -#if !GTK_CHECK_VERSION(3, 90, 0) - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), - TRUE); -#endif + if (!GtkCheckVersion(4)) { + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), + TRUE); + } g_signal_connect(dialog, "response", G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this); return dialog; @@ -622,8 +627,8 @@ void SelectFileDialogImplGTK::OnFileChooserDestroy(GtkWidget* dialog) { } } -#if !GTK_CHECK_VERSION(3, 90, 0) void SelectFileDialogImplGTK::OnUpdatePreview(GtkWidget* chooser) { + DCHECK(!GtkCheckVersion(4)); gchar* filename = gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(chooser)); if (!filename) { @@ -653,6 +658,5 @@ void SelectFileDialogImplGTK::OnUpdatePreview(GtkWidget* chooser) { gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), pixbuf ? TRUE : FALSE); } -#endif } // namespace gtk diff --git a/chromium/ui/gtk/select_file_dialog_impl_gtk.h b/chromium/ui/gtk/select_file_dialog_impl_gtk.h index 74966c1dd25..6db083d0cfc 100644 --- a/chromium/ui/gtk/select_file_dialog_impl_gtk.h +++ b/chromium/ui/gtk/select_file_dialog_impl_gtk.h @@ -5,6 +5,8 @@ #ifndef UI_GTK_SELECT_FILE_DIALOG_IMPL_GTK_H_ #define UI_GTK_SELECT_FILE_DIALOG_IMPL_GTK_H_ +#include + #include "base/macros.h" #include "ui/base/glib/glib_signal.h" #include "ui/gtk/gtk_util.h" @@ -29,7 +31,7 @@ class SelectFileDialogImplGTK : public SelectFileDialogImpl, // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -122,25 +124,22 @@ class SelectFileDialogImplGTK : public SelectFileDialogImpl, OnFileChooserDestroy, GtkWidget*); -#if !GTK_CHECK_VERSION(3, 90, 0) - // Callback for when we update the preview for the selection. + // Callback for when we update the preview for the selection. Only used on + // GTK3. CHROMEG_CALLBACK_0(SelectFileDialogImplGTK, void, OnUpdatePreview, GtkWidget*); -#endif // A map from dialog windows to the |params| user data associated with them. std::map params_map_; - // GTK4 provides its own preview. -#if !GTK_CHECK_VERSION(3, 90, 0) + // Only used on GTK3 since GTK4 provides its own preview. // The GtkImage widget for showing previews of selected images. GtkWidget* preview_ = nullptr; -#endif - // All our dialogs. - std::set dialogs_; + // Maps from dialogs to signal handler IDs. + std::map dialogs_; // The set of all parent windows for which we are currently running dialogs. std::set parents_; diff --git a/chromium/ui/gtk/select_file_dialog_impl_kde.cc b/chromium/ui/gtk/select_file_dialog_impl_kde.cc index 31f880ef527..972d5c015a9 100644 --- a/chromium/ui/gtk/select_file_dialog_impl_kde.cc +++ b/chromium/ui/gtk/select_file_dialog_impl_kde.cc @@ -58,7 +58,7 @@ class SelectFileDialogImplKDE : public SelectFileDialogImpl { // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -252,7 +252,7 @@ bool SelectFileDialogImplKDE::IsRunning(gfx::NativeWindow parent_window) const { // We ignore |default_extension|. void SelectFileDialogImplKDE::SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/gtk/settings_provider_gsettings.cc b/chromium/ui/gtk/settings_provider_gsettings.cc index 1430b5b66d1..6498b742888 100644 --- a/chromium/ui/gtk/settings_provider_gsettings.cc +++ b/chromium/ui/gtk/settings_provider_gsettings.cc @@ -51,8 +51,7 @@ SettingsProviderGSettings::SettingsProviderGSettings(GtkUi* delegate) g_settings_schema_source_get_default(), settings_schema, FALSE); if (!button_schema || !g_settings_schema_has_key(button_schema, kButtonLayoutKey) || - !(button_settings_ = - ScopedGObject(g_settings_new(settings_schema)))) { + !(button_settings_ = TakeGObject(g_settings_new(settings_schema)))) { ParseAndStoreButtonValue(kDefaultButtonString); } else { // Get the inital value of the keys we're interested in. @@ -68,7 +67,7 @@ SettingsProviderGSettings::SettingsProviderGSettings(GtkUi* delegate) if (click_schema && g_settings_schema_has_key(click_schema, kMiddleClickActionKey) && (click_settings_ = - ScopedGObject(g_settings_new(kGnomePreferencesSchema)))) { + TakeGObject(g_settings_new(kGnomePreferencesSchema)))) { OnMiddleClickActionChanged(click_settings_, kMiddleClickActionKey); signal_middle_click_id_ = g_signal_connect(click_settings_, kMiddleClickActionChangedSignal, diff --git a/chromium/ui/gtk/settings_provider_gtk.cc b/chromium/ui/gtk/settings_provider_gtk.cc index d67c2d08377..04a3c1e04d9 100644 --- a/chromium/ui/gtk/settings_provider_gtk.cc +++ b/chromium/ui/gtk/settings_provider_gtk.cc @@ -13,16 +13,13 @@ namespace gtk { namespace { std::string GetDecorationLayoutFromGtkWindow() { -#if GTK_CHECK_VERSION(3, 90, 0) +#if BUILDFLAG(GTK_VERSION) >= 4 NOTREACHED(); static const char kDefaultGtkLayout[] = "menu:minimize,maximize,close"; return kDefaultGtkLayout; #else - static ScopedStyleContext context; - if (!context) { - context = GetStyleContextFromCss(""); - gtk_style_context_add_class(context, "csd"); - } + 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, diff --git a/chromium/ui/gtk/wayland/BUILD.gn b/chromium/ui/gtk/wayland/BUILD.gn new file mode 100644 index 00000000000..599af208624 --- /dev/null +++ b/chromium/ui/gtk/wayland/BUILD.gn @@ -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("//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 new file mode 100644 index 00000000000..f075333af40 --- /dev/null +++ b/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.cc @@ -0,0 +1,91 @@ +// 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 + +#include "base/bind.h" +#include "base/callback.h" +#include "base/environment.h" +#include "base/logging.h" + +#if BUILDFLAG(GTK_VERSION) >= 4 +#include +#else +#include + +#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(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_delegate_wayland_base.h b/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.h new file mode 100644 index 00000000000..afab8a113a6 --- /dev/null +++ b/chromium/ui/gtk/wayland/gtk_ui_delegate_wayland_base.h @@ -0,0 +1,49 @@ +// 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_WAYLAND_GTK_UI_DELEGATE_WAYLAND_BASE_H_ +#define UI_GTK_WAYLAND_GTK_UI_DELEGATE_WAYLAND_BASE_H_ + +#include + +#include "base/callback_forward.h" +#include "base/component_export.h" +#include "base/memory/weak_ptr.h" +#include "ui/gtk/gtk_ui_delegate.h" + +namespace ui { + +class COMPONENT_EXPORT(GTK_WAYLAND) GtkUiDelegateWaylandBase + : public GtkUiDelegate { + public: + GtkUiDelegateWaylandBase(); + GtkUiDelegateWaylandBase(const GtkUiDelegateWaylandBase&) = delete; + GtkUiDelegateWaylandBase& operator=(const GtkUiDelegateWaylandBase&) = delete; + ~GtkUiDelegateWaylandBase() override; + + // GtkUiDelegate: + void OnInitialized(GtkWidget* widget) override; + GdkKeymap* GetGdkKeymap() override; + GdkWindow* GetGdkWindow(gfx::AcceleratedWidget window_id) override; + bool SetGtkWidgetTransientFor(GtkWidget* widget, + gfx::AcceleratedWidget parent) override; + void ClearTransientFor(gfx::AcceleratedWidget parent) override; + void ShowGtkWindow(GtkWindow* window) override; + + protected: + virtual bool SetGtkWidgetTransientForImpl( + gfx::AcceleratedWidget parent, + base::OnceCallback callback) = 0; + + private: + // Called when xdg-foreign exports a parent window passed in + // SetGtkWidgetTransientFor. + void OnHandle(GtkWidget* widget, const std::string& handle); + + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace ui + +#endif // UI_GTK_WAYLAND_GTK_UI_DELEGATE_WAYLAND_BASE_H_ diff --git a/chromium/ui/gtk/x/gtk_event_loop_x11.cc b/chromium/ui/gtk/x/gtk_event_loop_x11.cc index bfef18dc6b5..53007392631 100644 --- a/chromium/ui/gtk/x/gtk_event_loop_x11.cc +++ b/chromium/ui/gtk/x/gtk_event_loop_x11.cc @@ -8,12 +8,11 @@ #include #include -#include "base/memory/singleton.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/x/event.h" extern "C" { -#if GTK_CHECK_VERSION(3, 90, 0) +#if BUILDFLAG(GTK_VERSION) >= 4 unsigned long gdk_x11_surface_get_xid(GdkSurface* surface); #else unsigned long gdk_x11_window_get_xid(GdkWindow* window); @@ -30,7 +29,7 @@ x11::KeyButMask BuildXkbStateFromGdkEvent(unsigned int state, } x11::KeyEvent ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) { -#if GTK_CHECK_VERSION(3, 90, 0) +#if BUILDFLAG(GTK_VERSION) >= 4 GdkKeymapKey* keys = nullptr; guint* keyvals = nullptr; gint n_entries = 0; @@ -80,43 +79,7 @@ x11::KeyEvent ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) { #endif } -} // namespace - -// static -GtkEventLoopX11* GtkEventLoopX11::EnsureInstance() { - return base::Singleton::get(); -} - -GtkEventLoopX11::GtkEventLoopX11() { - gdk_event_handler_set(DispatchGdkEvent, nullptr, nullptr); -} - -GtkEventLoopX11::~GtkEventLoopX11() { - gdk_event_handler_set(reinterpret_cast(gtk_main_do_event), - nullptr, nullptr); -} - -// static -void GtkEventLoopX11::DispatchGdkEvent(GdkEvent* gdk_event, gpointer) { -#if GTK_CHECK_VERSION(3, 90, 0) - 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: - ProcessGdkEventKey(gdk_event); - break; - default: - break; // Do nothing. - } - - gtk_main_do_event(gdk_event); -} - -// static -void GtkEventLoopX11::ProcessGdkEventKey(GdkEvent* gdk_event) { +void ProcessGdkEvent(GdkEvent* gdk_event) { // This function translates GdkEventKeys into XKeyEvents and puts them to // the X event queue. // @@ -131,10 +94,57 @@ void GtkEventLoopX11::ProcessGdkEventKey(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; + } + // 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. x11::Connection::Get()->DispatchEvent( x11::Event{ConvertGdkEventToKeyEvent(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 +} + +GtkEventLoopX11::~GtkEventLoopX11() { +#if BUILDFLAG(GTK_VERSION) >= 4 + g_signal_handler_disconnect(surface_, signal_id_); +#else + gdk_event_handler_set(reinterpret_cast(gtk_main_do_event), + nullptr, nullptr); +#endif +} + +#if BUILDFLAG(GTK_VERSION) >= 4 +gboolean GtkEventLoopX11::OnEvent(GdkEvent* gdk_event) { + ProcessGdkEvent(gdk_event); + return false; +} +#else +// static +void GtkEventLoopX11::DispatchGdkEvent(GdkEvent* gdk_event, gpointer) { + ProcessGdkEvent(gdk_event); + gtk_main_do_event(gdk_event); +} +#endif + } // namespace ui diff --git a/chromium/ui/gtk/x/gtk_event_loop_x11.h b/chromium/ui/gtk/x/gtk_event_loop_x11.h index baa53a5b823..91cbe124268 100644 --- a/chromium/ui/gtk/x/gtk_event_loop_x11.h +++ b/chromium/ui/gtk/x/gtk_event_loop_x11.h @@ -6,31 +6,30 @@ #define UI_GTK_X_GTK_EVENT_LOOP_X11_H_ #include +#include #include "ui/base/glib/glib_integers.h" - -namespace base { -template -struct DefaultSingletonTraits; -} +#include "ui/base/glib/glib_signal.h" +#include "ui/gtk/gtk_buildflags.h" namespace ui { class GtkEventLoopX11 { public: - static GtkEventLoopX11* EnsureInstance(); + explicit GtkEventLoopX11(GtkWidget* widget); + ~GtkEventLoopX11(); GtkEventLoopX11(const GtkEventLoopX11&) = delete; GtkEventLoopX11& operator=(const GtkEventLoopX11&) = delete; private: - friend struct base::DefaultSingletonTraits; - - GtkEventLoopX11(); - ~GtkEventLoopX11(); - +#if BUILDFLAG(GTK_VERSION) >= 4 + CHROMEG_CALLBACK_0(GtkEventLoopX11, gboolean, OnEvent, GdkEvent*); + GdkSurface* surface_ = nullptr; + gulong signal_id_ = 0; +#else static void DispatchGdkEvent(GdkEvent* gdk_event, gpointer); - static void ProcessGdkEventKey(GdkEvent* gdk_event); +#endif }; } // namespace ui diff --git a/chromium/ui/gtk/x/gtk_ui_delegate_x11.cc b/chromium/ui/gtk/x/gtk_ui_delegate_x11.cc index 2160c8543b8..618d0865860 100644 --- a/chromium/ui/gtk/x/gtk_ui_delegate_x11.cc +++ b/chromium/ui/gtk/x/gtk_ui_delegate_x11.cc @@ -11,6 +11,7 @@ #include "ui/base/x/x11_util.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/xlib_support.h" #include "ui/gfx/x/xproto.h" #include "ui/gfx/x/xproto_util.h" @@ -25,7 +26,11 @@ GdkWindow* gdk_x11_window_foreign_new_for_display(GdkDisplay* display, 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 { @@ -42,9 +47,10 @@ GtkUiDelegateX11::GtkUiDelegateX11(x11::Connection* connection) GtkUiDelegateX11::~GtkUiDelegateX11() = default; -void GtkUiDelegateX11::OnInitialized() { +void GtkUiDelegateX11::OnInitialized(GtkWidget* widget) { // Ensure the singleton instance of GtkEventLoopX11 is created and started. - GtkEventLoopX11::EnsureInstance(); + if (!event_loop_) + event_loop_ = std::make_unique(widget); // GTK sets an Xlib error handler that exits the process on any async errors. // We don't want this behavior, so reset the error handler to something that @@ -53,10 +59,20 @@ void GtkUiDelegateX11::OnInitialized() { } GdkKeymap* GtkUiDelegateX11::GetGdkKeymap() { +#if BUILDFLAG(GTK_VERSION) >= 4 + NOTREACHED(); + return nullptr; +#else 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 GdkDisplay* display = GetGdkDisplay(); GdkWindow* gdk_window = gdk_x11_window_lookup_for_display( display, static_cast(window_id)); @@ -66,13 +82,22 @@ GdkWindow* GtkUiDelegateX11::GetGdkWindow(gfx::AcceleratedWidget window_id) { gdk_window = gdk_x11_window_foreign_new_for_display( display, static_cast(window_id)); return gdk_window; +#endif } -bool GtkUiDelegateX11::SetGdkWindowTransientFor(GdkWindow* window, +bool GtkUiDelegateX11::SetGtkWidgetTransientFor(GtkWidget* widget, gfx::AcceleratedWidget parent) { - auto x11_window = static_cast(gdk_x11_window_get_xid(window)); +#if BUILDFLAG(GTK_VERSION) >= 4 + auto x11_window = static_cast(gdk_x11_surface_get_xid( + gtk_native_get_surface(gtk_widget_get_native(widget)))); +#else + auto x11_window = static_cast( + gdk_x11_window_get_xid(gtk_widget_get_window(widget))); +#endif SetProperty(x11_window, x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW, parent); + SetProperty(x11_window, x11::GetAtom("_NET_WM_WINDOW_TYPE"), x11::Atom::ATOM, + x11::GetAtom("_NET_WM_WINDOW_TYPE_DIALOG")); ui::X11Window* parent_window = ui::X11WindowManager::GetInstance()->GetWindow(parent); diff --git a/chromium/ui/gtk/x/gtk_ui_delegate_x11.h b/chromium/ui/gtk/x/gtk_ui_delegate_x11.h index e92f9a3c886..334f79930c9 100644 --- a/chromium/ui/gtk/x/gtk_ui_delegate_x11.h +++ b/chromium/ui/gtk/x/gtk_ui_delegate_x11.h @@ -14,6 +14,8 @@ using GdkDisplay = struct _GdkDisplay; namespace ui { +class GtkEventLoopX11; + // GtkUiDelegate implementation for desktop Linux X11 backends. // // TODO(crbug.com/1002674): For now, this is used by both Aura (legacy) and @@ -27,10 +29,10 @@ class COMPONENT_EXPORT(UI_GTK_X) GtkUiDelegateX11 : public GtkUiDelegate { ~GtkUiDelegateX11() override; // GtkUiDelegate: - void OnInitialized() override; + void OnInitialized(GtkWidget* widget) override; GdkKeymap* GetGdkKeymap() override; GdkWindow* GetGdkWindow(gfx::AcceleratedWidget window_id) override; - bool SetGdkWindowTransientFor(GdkWindow* window, + bool SetGtkWidgetTransientFor(GtkWidget* widget, gfx::AcceleratedWidget parent) override; void ClearTransientFor(gfx::AcceleratedWidget parent) override; void ShowGtkWindow(GtkWindow* window) override; @@ -41,6 +43,7 @@ class COMPONENT_EXPORT(UI_GTK_X) GtkUiDelegateX11 : public GtkUiDelegate { x11::Connection* const connection_; GdkDisplay* display_ = nullptr; + std::unique_ptr event_loop_; }; } // namespace ui diff --git a/chromium/ui/latency/latency_info.cc b/chromium/ui/latency/latency_info.cc index e0811de9f03..6053c6f5199 100644 --- a/chromium/ui/latency/latency_info.cc +++ b/chromium/ui/latency/latency_info.cc @@ -306,9 +306,14 @@ void LatencyInfo::Terminate() { terminated_ = true; if (*g_latency_info_enabled.Get().latency_info_enabled) { + base::TimeTicks gpu_swap_end_timestamp; + if (!this->FindLatency(INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT, + &gpu_swap_end_timestamp)) { + gpu_swap_end_timestamp = base::TimeTicks::Now(); + } TRACE_EVENT_END( kTraceCategoriesForAsyncEvents, perfetto::Track::Global(trace_id_), - [this](perfetto::EventContext ctx) { + gpu_swap_end_timestamp, [this](perfetto::EventContext ctx) { ChromeLatencyInfo* info = ctx.event()->set_chrome_latency_info(); for (const auto& lc : latency_components_) { ChromeLatencyInfo::ComponentInfo* component = diff --git a/chromium/ui/latency/latency_tracker.cc b/chromium/ui/latency/latency_tracker.cc index 0f89e2cf3d6..7fe3a9290a5 100644 --- a/chromium/ui/latency/latency_tracker.cc +++ b/chromium/ui/latency/latency_tracker.cc @@ -4,7 +4,6 @@ #include "ui/latency/latency_tracker.h" -#include #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" @@ -50,55 +49,43 @@ bool IsInertialScroll(const LatencyInfo& latency) { return latency.source_event_type() == ui::SourceEventType::INERTIAL; } -bool LatencyTraceIdCompare(const LatencyInfo& i, const LatencyInfo& j) { - return i.trace_id() < j.trace_id(); -} - } // namespace LatencyTracker::LatencyTracker() = default; LatencyTracker::~LatencyTracker() = default; void LatencyTracker::OnGpuSwapBuffersCompleted( - const std::vector& latency_info, + std::vector latency_info, bool top_controls_visible_height_changed) { - // Sort latency_info as they can be in incorrect order. - std::vector latency_infos(latency_info); - std::sort(latency_infos.begin(), latency_infos.end(), LatencyTraceIdCompare); - for (const auto& latency : latency_infos) - OnGpuSwapBuffersCompleted(latency, top_controls_visible_height_changed); -} - -void LatencyTracker::OnGpuSwapBuffersCompleted( - const LatencyInfo& latency, - bool top_controls_visible_height_changed) { - base::TimeTicks gpu_swap_end_timestamp; - if (!latency.FindLatency(INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT, - &gpu_swap_end_timestamp)) { - return; - } + for (const auto& latency : latency_info) { + base::TimeTicks gpu_swap_end_timestamp; + if (!latency.FindLatency(INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT, + &gpu_swap_end_timestamp)) { + continue; + } - base::TimeTicks gpu_swap_begin_timestamp; - bool found_component = latency.FindLatency( - ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, &gpu_swap_begin_timestamp); - DCHECK_AND_RETURN_ON_FAIL(found_component); + base::TimeTicks gpu_swap_begin_timestamp; + bool found_component = latency.FindLatency( + ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, &gpu_swap_begin_timestamp); + DCHECK_AND_RETURN_ON_FAIL(found_component); - if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, - nullptr)) { - return; - } + if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, + nullptr)) { + continue; + } - ui::SourceEventType source_event_type = latency.source_event_type(); - if (source_event_type == ui::SourceEventType::WHEEL || - source_event_type == ui::SourceEventType::MOUSE || - source_event_type == ui::SourceEventType::TOUCH || - source_event_type == ui::SourceEventType::INERTIAL || - source_event_type == ui::SourceEventType::KEY_PRESS || - source_event_type == ui::SourceEventType::TOUCHPAD || - source_event_type == ui::SourceEventType::SCROLLBAR) { - ComputeEndToEndLatencyHistograms(gpu_swap_begin_timestamp, - gpu_swap_end_timestamp, latency, - top_controls_visible_height_changed); + ui::SourceEventType source_event_type = latency.source_event_type(); + if (source_event_type == ui::SourceEventType::WHEEL || + source_event_type == ui::SourceEventType::MOUSE || + source_event_type == ui::SourceEventType::TOUCH || + source_event_type == ui::SourceEventType::INERTIAL || + source_event_type == ui::SourceEventType::KEY_PRESS || + source_event_type == ui::SourceEventType::TOUCHPAD || + source_event_type == ui::SourceEventType::SCROLLBAR) { + ComputeEndToEndLatencyHistograms(gpu_swap_begin_timestamp, + gpu_swap_end_timestamp, latency, + top_controls_visible_height_changed); + } } } @@ -147,6 +134,56 @@ void LatencyTracker::ReportUkmScrollLatency( builder.Record(ukm_recorder); } +void LatencyTracker::ReportJankyFrame(base::TimeTicks original_timestamp, + base::TimeTicks gpu_swap_end_timestamp, + const ui::LatencyInfo& latency, + bool first_frame) { + CONFIRM_EVENT_TIMES_EXIST(original_timestamp, gpu_swap_end_timestamp); + base::TimeDelta dur = gpu_swap_end_timestamp - original_timestamp; + + // 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) { + // TODO(185884172): Investigate using proper vsync interval. + + // Assuming 60fps, each frame is rendered in (1/60) of a second. + // To see how many of those intervals fit into the real frame timing, + // we divide it on 1/60 which is the same thing as multiplying by 60. + double frames_taken = dur.InSecondsF() * 60; + double prev_frames_taken = prev_duration_.InSecondsF() * 60; + + // For each GestureScroll update, we would like to report whether it was + // janky. However, in order to do that, we need to compare it both to the + // previous as well as to the next event. This condition means that no jank + // was reported for the previous frame (as compared to the one before that), + // so we need to compare it to the current one and report whether it's + // janky: + 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); + } + + // 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); + + // 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 + // report every GestureScrollUpdate only once. + prev_scroll_update_reported_ = true; + } else { + // We do not have enough information to report whether the current event + // is janky, and need to compare it to the next one before reporting + // anything about it. + prev_scroll_update_reported_ = false; + } + } + + prev_duration_ = dur; +} + void LatencyTracker::ComputeEndToEndLatencyHistograms( base::TimeTicks gpu_swap_begin_timestamp, base::TimeTicks gpu_swap_end_timestamp, @@ -165,6 +202,7 @@ void LatencyTracker::ComputeEndToEndLatencyHistograms( &original_timestamp)) { DCHECK(input_modality == "Wheel" || input_modality == "Touch" || input_modality == "Scrollbar"); + ReportJankyFrame(original_timestamp, gpu_swap_end_timestamp, latency, true); // For inertial scrolling we don't separate the first event from the rest of // them. @@ -203,6 +241,9 @@ void LatencyTracker::ComputeEndToEndLatencyHistograms( &original_timestamp)) { DCHECK(input_modality == "Wheel" || input_modality == "Touch" || input_modality == "Scrollbar"); + ReportJankyFrame(original_timestamp, gpu_swap_end_timestamp, latency, + false); + // For inertial scrolling we don't separate the first event from the rest of // them. scroll_name = IsInertialScroll(latency) ? "ScrollInertial" : "ScrollUpdate"; diff --git a/chromium/ui/latency/latency_tracker.h b/chromium/ui/latency/latency_tracker.h index 88f56c4a41b..55e8ac1e9cb 100644 --- a/chromium/ui/latency/latency_tracker.h +++ b/chromium/ui/latency/latency_tracker.h @@ -22,7 +22,7 @@ class LatencyTracker { // performing relevant UMA latency reporting. // Called when GPU buffers swap completes. void OnGpuSwapBuffersCompleted( - const std::vector& latency_info, + std::vector latency_info, bool top_controls_visible_height_changed = false); private: @@ -35,8 +35,8 @@ class LatencyTracker { INPUT_METRIC_EVENT_MAX = SCROLL_UPDATE_WHEEL }; - void OnGpuSwapBuffersCompleted(const LatencyInfo& latency, - bool top_controls_visible_height_changed); + base::TimeDelta prev_duration_; + bool prev_scroll_update_reported_ = false; void ReportUkmScrollLatency( const InputMetricEvent& metric_event, @@ -52,6 +52,11 @@ class LatencyTracker { const LatencyInfo& latency, bool top_controls_visible_height_changed); + void ReportJankyFrame(base::TimeTicks gpu_swap_begin_timestamp, + base::TimeTicks gpu_swap_end_timestamp, + const LatencyInfo& latency, + bool first_frame); + DISALLOW_COPY_AND_ASSIGN(LatencyTracker); }; diff --git a/chromium/ui/login/BUILD.gn b/chromium/ui/login/BUILD.gn deleted file mode 100644 index 6acddfc8f3b..00000000000 --- a/chromium/ui/login/BUILD.gn +++ /dev/null @@ -1,11 +0,0 @@ -# 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. - -import("//third_party/closure_compiler/compile_js.gni") - -js_library("display_manager_types") { -} - -js_library("login_ui_tools") { -} diff --git a/chromium/ui/login/DIR_METADATA b/chromium/ui/login/DIR_METADATA deleted file mode 100644 index a4805830559..00000000000 --- a/chromium/ui/login/DIR_METADATA +++ /dev/null @@ -1,3 +0,0 @@ -monorail: { - component: "UI>Shell>OOBE" -} diff --git a/chromium/ui/login/OWNERS b/chromium/ui/login/OWNERS deleted file mode 100644 index 43c2ba77ae7..00000000000 --- a/chromium/ui/login/OWNERS +++ /dev/null @@ -1,9 +0,0 @@ -# (in PST) -achuith@chromium.org -alemate@chromium.org -tbarzic@chromium.org -xiyuan@chromium.org - -# (in CET) -antrim@chromium.org -rsorokin@chromium.org diff --git a/chromium/ui/login/bubble.css b/chromium/ui/login/bubble.css deleted file mode 100644 index 29d618b9038..00000000000 --- a/chromium/ui/login/bubble.css +++ /dev/null @@ -1,173 +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. - * - * Css based bubble. - */ - -.bubble { - background: rgba(0, 0, 0, 0.8); - border-radius: 2px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - color: rgba(255, 255, 255, 0.87); - font-size: 12px; - margin: 2px; - max-width: 240px; - padding: 8px; - position: absolute; - transition: opacity 200ms ease-in-out; -} - -body.chromeos .bubble { - margin: unset; - padding: 14px; -} - -/* --- oldstyle begin --- */ - -.bubble[oldstyle] { - background: white; - border: 1px solid rgba(0, 0, 0, 0.25); - color: unset; -} - -.bubble[oldstyle]::before { - border-style: solid; - border-width: 8px; - content: ''; - display: block; - position: absolute; -} - -.bubble-top::before { - border-color: rgba(0, 0, 0, 0.25) transparent transparent transparent; - bottom: -16px; -} - -html[dir=ltr] .bubble-top::before { - left: 17px; -} - -html[dir=rtl] .bubble-top::before { - right: 17px; -} - -html[dir=ltr] .bubble-right::before, -html[dir=rtl] .bubble-left::before { - border-color: transparent rgba(0, 0, 0, 0.25) transparent transparent; - left: -16px; - top: 17px; -} - -.bubble-bottom::before { - border-color: transparent transparent rgba(0, 0, 0, 0.25) transparent; - top: -16px; -} - -html[dir=ltr] .bubble-bottom::before { - left: 17px; -} - -html[dir=rtl] .bubble-bottom::before { - right: 17px; -} - -html[dir=ltr] .bubble-left::before, -html[dir=rtl] .bubble-right::before { - border-color: transparent transparent transparent rgba(0, 0, 0, 0.25); - right: -16px; - top: 17px; -} - -.bubble[oldstyle]::after { - border-style: solid; - border-width: 8px; - content: ''; - display: block; - position: absolute; -} - -.bubble-top::after { - border-color: white transparent transparent transparent; - bottom: -15px; -} - -html[dir=ltr] .bubble-top::after { - left: 17px; -} - -html[dir=rtl] .bubble-top::after { - right: 17px; -} - -html[dir=ltr] .bubble-right::after, -html[dir=rtl] .bubble-left::after { - border-color: transparent white transparent transparent; - left: -15px; - top: 17px; -} - -.bubble-bottom::after { - border-color: transparent transparent white transparent; - top: -15px; -} - -html[dir=ltr] .bubble-bottom::after { - left: 17px; -} - -html[dir=rtl] .bubble-bottom::after { - right: 17px; -} - -html[dir=ltr] .bubble-left::after, -html[dir=rtl] .bubble-right::after { - border-color: transparent transparent transparent white; - right: -15px; - top: 17px; -} - -/* --- oldstyle end --- */ - -body.chromeos .error-message-bubble::before { - -webkit-mask-image: url(../../ui/webui/resources/images/warning.svg); - -webkit-mask-position: left top; - -webkit-mask-repeat: no-repeat; - -webkit-mask-size: 20px; - background-color: rgb(255,255,255); - content: ''; - display: block; - height: 20px; - left: 14px; - position: absolute; - top: 10px; - width: 20px; -} - -body:not(.chromeos) .error-message-bubble { - -webkit-padding-start: 30px; - background: url(chrome://theme/IDR_WARNING) left top no-repeat; - background-size: 24px; -} - -body.chromeos .error-message-bubble { - padding-top: 19px; -} - -.bubble[match-width] .error-message-bubble { - -webkit-padding-start: unset; - padding-top: 20px; -} - -body.chromeos .bubble a { - color: #7baaf7; - text-decoration: none; -} - -.error-message-bubble-padding { - margin-bottom: 10px; -} - -html[dir=rtl] .error-message-bubble { - background-position: right top; -} diff --git a/chromium/ui/login/bubble.js b/chromium/ui/login/bubble.js deleted file mode 100644 index 60ef133f8f4..00000000000 --- a/chromium/ui/login/bubble.js +++ /dev/null @@ -1,433 +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. - -/** - * @fileoverview Bubble implementation. - */ - -// TODO(xiyuan): Move this into shared. -cr.define('cr.ui', function() { - /** - * Creates a bubble div. - * @constructor - * @extends {HTMLDivElement} - */ - var Bubble = cr.ui.define('div'); - - /** - * Bubble key codes. - * @enum {number} - */ - var Keys = { - TAB: 'Tab', - ENTER: 'Enter', - ESC: 'Escape', - SPACE: ' ' - }; - - /** - * Bubble attachment side. - * @enum {number} - */ - Bubble.Attachment = { - RIGHT: 0, - LEFT: 1, - TOP: 2, - BOTTOM: 3 - }; - - Bubble.prototype = { - __proto__: HTMLDivElement.prototype, - - // Anchor element for this bubble. - anchor_: undefined, - - // If defined, sets focus to this element once bubble is closed. Focus is - // set to this element only if there's no any other focused element. - elementToFocusOnHide_: undefined, - - // With help of these elements we create closed artificial tab-cycle through - // bubble elements. - firstBubbleElement_: undefined, - lastBubbleElement_: undefined, - - // Whether to hide bubble when key is pressed. - hideOnKeyPress_: true, - - persistent_: false, - - /** @override */ - decorate: function() { - this.docKeyDownHandler_ = this.handleDocKeyDown_.bind(this); - this.selfClickHandler_ = this.handleSelfClick_.bind(this); - this.ownerDocument.addEventListener('click', - this.handleDocClick_.bind(this)); - // Set useCapture to true because scroll event does not bubble. - this.ownerDocument.addEventListener('scroll', - this.handleScroll_.bind(this), - true); - this.ownerDocument.addEventListener('keydown', - this.docKeyDownHandler_); - window.addEventListener('blur', this.handleWindowBlur_.bind(this)); - this.addEventListener('transitionend', - this.handleTransitionEnd_.bind(this)); - // Guard timer for 200ms + epsilon. - ensureTransitionEndEvent(this, 250); - }, - - /** - * Element that should be focused on hide. - * @type {HTMLElement} - */ - set elementToFocusOnHide(value) { - this.elementToFocusOnHide_ = value; - }, - - /** - * Element that should be focused on shift-tab of first bubble element - * to create artificial closed tab-cycle through bubble. - * Usually close-button. - * @type {HTMLElement} - */ - set lastBubbleElement(value) { - this.lastBubbleElement_ = value; - }, - - /** - * Whether the bubble should remain shown on user action events (e.g. on - * user clicking, or scrolling outside the bubble). Note that - * {@code this.hideOnKeyPress} has precedence. - * @type {boolean} - */ - set persistent(value) { - this.persistent_ = value - }, - - /** - * If set, the element at which the bubble is anchored. - * @type {HTMLElement|undefined} - */ - get anchor() { - return this.anchor_; - }, - - /** - * Element that should be focused on tab of last bubble element - * to create artificial closed tab-cycle through bubble. - * Same element as first focused on bubble opening. - * @type {HTMLElement} - */ - set firstBubbleElement(value) { - this.firstBubbleElement_ = value; - }, - - /** - * Whether to hide bubble when key is pressed. - * @type {boolean} - */ - set hideOnKeyPress(value) { - this.hideOnKeyPress_ = value; - }, - - /** - * Whether to hide bubble when clicked inside bubble element. - * Default is true. - * @type {boolean} - */ - set hideOnSelfClick(value) { - if (value) - this.removeEventListener('click', this.selfClickHandler_); - else - this.addEventListener('click', this.selfClickHandler_); - }, - - /** - * Handler for click event which prevents bubble auto hide. - * @private - */ - handleSelfClick_: function(e) { - // Allow clicking on [x] button. - if (e.target && e.target.classList.contains('close-button')) - return; - e.stopPropagation(); - }, - - /** - * Sets the attachment of the bubble. - * @param {!Attachment} attachment Bubble attachment. - */ - setAttachment_: function(attachment) { - var styleClassList = ['bubble-right', 'bubble-left', - 'bubble-top', 'bubble-bottom']; - for (var i = 0; i < styleClassList.length; ++i) - this.classList.toggle(styleClassList[i], i == attachment); - }, - - /** - * Shows the bubble for given anchor element. - * @param {!Object} pos Bubble position (left, top, right, bottom in px). - * @param {HTMLElement} opt_content Content to show in bubble. - * If not specified, bubble element content is shown. - * @param {Attachment=} opt_attachment Bubble attachment (on which side of - * the element it should be displayed). - * @param {boolean=} opt_oldstyle Optional flag to force old style bubble, - * i.e. pre-MD-style. - * @private - */ - showContentAt_: function(pos, opt_content, opt_attachment, opt_oldstyle) { - this.style.top = this.style.left = this.style.right = this.style.bottom = - 'auto'; - for (var k in pos) { - if (typeof pos[k] == 'number') - this.style[k] = pos[k] + 'px'; - } - if (opt_content !== undefined) - this.replaceContent(opt_content); - - if (opt_oldstyle) { - this.setAttribute('oldstyle', ''); - this.setAttachment_(opt_attachment); - } - - this.hidden = false; - this.classList.remove('faded'); - }, - - /** - * Replaces error message content with the given DOM element. - * @param {HTMLElement} content Content to show in bubble. - */ - replaceContent: function(content) { - this.innerHTML = ''; - this.appendChild(content); - }, - - /** - * Shows the bubble for given anchor element. Bubble content is not cleared. - * @param {!HTMLElement} el Anchor element of the bubble. - * @param {!Attachment} attachment Bubble attachment (on which side of the - * element it should be displayed). - * @param {number=} opt_offset Offset of the bubble. - * @param {number=} opt_padding Optional padding of the bubble. - */ - showForElement: function(el, attachment, opt_offset, opt_padding) { - /* showForElement() is used only to display Accessibility popup in - * oobe_screen_welcome*. It requires old-style bubble, so it is safe - * to always set this flag here. - */ - this.showContentForElement( - el, attachment, undefined, opt_offset, opt_padding, undefined, true); - }, - - /** - * Shows the bubble for given anchor element. - * @param {!HTMLElement} el Anchor element of the bubble. - * @param {!Attachment} attachment Bubble attachment (on which side of the - * element it should be displayed). - * @param {HTMLElement} opt_content Content to show in bubble. - * If not specified, bubble element content is shown. - * @param {number=} opt_offset Offset of the bubble attachment point from - * left (for vertical attachment) or top (for horizontal attachment) - * side of the element. If not specified, the bubble is positioned to - * be aligned with the left/top side of the element but not farther than - * half of its width/height. - * @param {number=} opt_padding Optional padding of the bubble. - * @param {boolean=} opt_match_width Optional flag to force the bubble have - * the same width as the element it it attached to. - * @param {boolean=} opt_oldstyle Optional flag to force old style bubble, - * i.e. pre-MD-style. - */ - showContentForElement: function( - el, attachment, opt_content, opt_offset, opt_padding, opt_match_width, - opt_oldstyle) { - /** @const */ var ARROW_OFFSET = 25; - /** @const */ var DEFAULT_PADDING = 18; - - if (opt_padding == undefined) - opt_padding = DEFAULT_PADDING; - - if (!opt_oldstyle) - opt_padding += 10; - - var origin = cr.ui.login.DisplayManager.getPosition(el); - var offset = opt_offset == undefined ? - [Math.min(ARROW_OFFSET, el.offsetWidth / 2), - Math.min(ARROW_OFFSET, el.offsetHeight / 2)] : - [opt_offset, opt_offset]; - - var pos = {}; - if (isRTL()) { - switch (attachment) { - case Bubble.Attachment.TOP: - pos.right = origin.right + offset[0] - ARROW_OFFSET; - pos.bottom = origin.bottom + el.offsetHeight + opt_padding; - break; - case Bubble.Attachment.RIGHT: - pos.top = origin.top + offset[1] - ARROW_OFFSET; - pos.right = origin.right + el.offsetWidth + opt_padding; - break; - case Bubble.Attachment.BOTTOM: - pos.right = origin.right + offset[0] - ARROW_OFFSET; - pos.top = origin.top + el.offsetHeight + opt_padding; - break; - case Bubble.Attachment.LEFT: - pos.top = origin.top + offset[1] - ARROW_OFFSET; - pos.left = origin.left + el.offsetWidth + opt_padding; - break; - } - } else { - switch (attachment) { - case Bubble.Attachment.TOP: - pos.left = origin.left + offset[0] - ARROW_OFFSET; - pos.bottom = origin.bottom + el.offsetHeight + opt_padding; - break; - case Bubble.Attachment.RIGHT: - pos.top = origin.top + offset[1] - ARROW_OFFSET; - pos.left = origin.left + el.offsetWidth + opt_padding; - break; - case Bubble.Attachment.BOTTOM: - pos.left = origin.left + offset[0] - ARROW_OFFSET; - pos.top = origin.top + el.offsetHeight + opt_padding; - break; - case Bubble.Attachment.LEFT: - pos.top = origin.top + offset[1] - ARROW_OFFSET; - pos.right = origin.right + el.offsetWidth + opt_padding; - break; - } - } - this.style.width = ''; - this.removeAttribute('match-width'); - if (opt_match_width) { - this.setAttribute('match-width', ''); - var elWidth = - window.getComputedStyle(el, null).getPropertyValue('width'); - var paddingLeft = parseInt(window.getComputedStyle(this, null) - .getPropertyValue('padding-left')); - var paddingRight = parseInt(window.getComputedStyle(this, null) - .getPropertyValue('padding-right')); - if (elWidth) - this.style.width = - (parseInt(elWidth) - paddingLeft - paddingRight) + 'px'; - } - - this.anchor_ = el; - this.showContentAt_(pos, opt_content, attachment, opt_oldstyle); - }, - - /** - * Shows the bubble for given anchor element. - * @param {!HTMLElement} el Anchor element of the bubble. - * @param {string} text Text content to show in bubble. - * @param {!Attachment} attachment Bubble attachment (on which side of the - * element it should be displayed). - * @param {number=} opt_offset Offset of the bubble attachment point from - * left (for vertical attachment) or top (for horizontal attachment) - * side of the element. If not specified, the bubble is positioned to - * be aligned with the left/top side of the element but not farther than - * half of its weight/height. - * @param {number=} opt_padding Optional padding of the bubble. - */ - showTextForElement: function( - el, text, attachment, opt_offset, opt_padding) { - var span = this.ownerDocument.createElement('span'); - span.textContent = text; - this.showContentForElement(el, attachment, span, opt_offset, opt_padding); - }, - - /** - * Hides the bubble. - */ - hide: function() { - if (!this.classList.contains('faded')) - this.classList.add('faded'); - }, - - /** - * Hides the bubble anchored to the given element (if any). - * @param {!Object} el Anchor element. - */ - hideForElement: function(el) { - if (!this.hidden && this.anchor_ == el) - this.hide(); - }, - - /** - * Handler for faded transition end. - * @private - */ - handleTransitionEnd_: function(e) { - if (this.classList.contains('faded')) { - this.hidden = true; - if (this.elementToFocusOnHide_) - this.elementToFocusOnHide_.focus(); - } - }, - - /** - * Handler of scroll event. - * @private - */ - handleScroll_: function(e) { - if (!this.hidden && !this.persistent_) - this.hide(); - }, - - /** - * Handler of document click event. - * @private - */ - handleDocClick_: function(e) { - // Ignore clicks on anchor element. - if (e.target == this.anchor_) - return; - - if (!this.hidden && !this.persistent_) - this.hide(); - }, - - /** - * Handle of document keydown event. - * @private - */ - handleDocKeyDown_: function(e) { - if (this.hidden) - return; - - if (this.hideOnKeyPress_) { - this.hide(); - return; - } - // Artificial tab-cycle. - - if (e.key == Keys.TAB && e.shiftKey == true && - e.target == this.firstBubbleElement_) { - this.lastBubbleElement_.focus(); - e.preventDefault(); - } - if (e.key == Keys.TAB && e.shiftKey == false && - e.target == this.lastBubbleElement_) { - this.firstBubbleElement_.focus(); - e.preventDefault(); - } - // Close bubble on ESC or on hitting spacebar or Enter at close-button. - if ((e.key == Keys.ESC && !this.persistent_) || - ((e.key == Keys.ENTER || e.key == Keys.SPACE) && e.target && - e.target.classList.contains('close-button'))) - this.hide(); - }, - - /** - * Handler of window blur event. - * @private - */ - handleWindowBlur_: function(e) { - if (!this.hidden && !this.persistent_) - this.hide(); - } - }; - - return { - Bubble: Bubble - }; -}); diff --git a/chromium/ui/login/display_manager.js b/chromium/ui/login/display_manager.js deleted file mode 100644 index f9631c6182c..00000000000 --- a/chromium/ui/login/display_manager.js +++ /dev/null @@ -1,961 +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. - -/** - * @fileoverview Display manager for WebUI OOBE and login. - */ - -// - -// TODO(xiyuan): Find a better to share those constants. -/** @const */ var SCREEN_WELCOME = 'connect'; -/** @const */ var SCREEN_OOBE_NETWORK = 'network-selection'; -/** @const */ var SCREEN_OOBE_HID_DETECTION = 'hid-detection'; -/** @const */ var SCREEN_OOBE_ENABLE_DEBUGGING = 'debugging'; -/** @const */ var SCREEN_OOBE_UPDATE = 'oobe-update'; -/** @const */ var SCREEN_OOBE_RESET = 'reset'; -/** @const */ var SCREEN_OOBE_ENROLLMENT = 'enterprise-enrollment'; -/** @const */ var SCREEN_OOBE_DEMO_SETUP = 'demo-setup'; -/** @const */ var SCREEN_OOBE_DEMO_PREFERENCES = 'demo-preferences'; -/** @const */ var SCREEN_OOBE_KIOSK_ENABLE = 'kiosk-enable'; -/** @const */ var SCREEN_PACKAGED_LICENSE = 'packaged-license'; -/** @const */ var SCREEN_GAIA_SIGNIN = 'gaia-signin'; -/** @const */ var SCREEN_ERROR_MESSAGE = 'error-message'; -/** @const */ var SCREEN_PASSWORD_CHANGED = 'gaia-password-changed'; -/** @const */ var SCREEN_APP_LAUNCH_SPLASH = 'app-launch-splash'; -/** @const */ var SCREEN_CONFIRM_PASSWORD = 'saml-confirm-password'; -/** @const */ var SCREEN_FATAL_ERROR = 'fatal-error'; -/** @const */ var SCREEN_KIOSK_ENABLE = 'kiosk-enable'; -/** @const */ var SCREEN_TERMS_OF_SERVICE = 'terms-of-service'; -/** @const */ var SCREEN_ARC_TERMS_OF_SERVICE = 'arc-tos'; -/** @const */ var SCREEN_DEVICE_DISABLED = 'device-disabled'; -/** @const */ var SCREEN_UPDATE_REQUIRED = 'update-required'; -/** @const */ var SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE = - 'ad-password-change'; -/** @const */ var SCREEN_SYNC_CONSENT = 'sync-consent'; -/** @const */ var SCREEN_FINGERPRINT_SETUP = 'fingerprint-setup'; -/** @const */ var SCREEN_RECOMMEND_APPS = 'recommend-apps'; -/** @const */ var SCREEN_APP_DOWNLOADING = 'app-downloading'; -/** @const */ var SCREEN_DISCOVER = 'discover'; -/** @const */ var SCREEN_MARKETING_OPT_IN = 'marketing-opt-in'; - -/* Accelerator identifiers. - * Must be kept in sync with webui_accelerator_mapping.cc. - */ -/** @const */ var ACCELERATOR_CANCEL = 'cancel'; -/** @const */ var ACCELERATOR_VERSION = 'version'; -/** @const */ var ACCELERATOR_RESET = 'reset'; -/** @const */ var ACCELERATOR_APP_LAUNCH_BAILOUT = 'app_launch_bailout'; -/** @const */ var ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG = - 'app_launch_network_config'; - -/** @const */ var USER_ACTION_ROLLBACK_TOGGLED = 'rollback-toggled'; - -cr.define('cr.ui.login', function() { - var Bubble = cr.ui.Bubble; - - /** - * Maximum time in milliseconds to wait for step transition to finish. - * The value is used as the duration for ensureTransitionEndEvent below. - * It needs to be inline with the step screen transition duration time - * defined in css file. The current value in css is 200ms. To avoid emulated - * transitionend fired before real one, 250ms is used. - * @const - */ - var MAX_SCREEN_TRANSITION_DURATION = 250; - - /** - * Group of screens (screen IDs) where factory-reset screen invocation is - * available. Newer screens using Polymer use the attribute - * `resetAllowed` in their `ready()` method. - * @type Array - * @const - */ - var RESET_AVAILABLE_SCREEN_GROUP = [ - SCREEN_OOBE_NETWORK, - SCREEN_GAIA_SIGNIN, - SCREEN_KIOSK_ENABLE, - SCREEN_ERROR_MESSAGE, - SCREEN_PASSWORD_CHANGED, - SCREEN_ARC_TERMS_OF_SERVICE, - SCREEN_CONFIRM_PASSWORD, - SCREEN_UPDATE_REQUIRED, - SCREEN_SYNC_CONSENT, - SCREEN_APP_DOWNLOADING, - SCREEN_DISCOVER, - SCREEN_MARKETING_OPT_IN, - ]; - - /** - * As Polymer behaviors do not provide true inheritance, when two behaviors - * would declare same method one of them will be hidden. Also, if element - * re-declares the method it needs explicitly iterate over behaviors and call - * method on them. This function simplifies such interaction by calling - * method on element and all behaviors in the same order as lifecycle - * callbacks are called. - * @param {Element} element - * @param {string} name function name - * @param {...*} arguments arguments for the function - */ - var invokePolymerMethod = function(element, name, ...arguments) { - let method = element[name]; - if (!method || typeof method !== 'function') - return; - method.apply(element, arguments); - if (!element.behaviors) - return; - - // If element has behaviors call functions on them in reverse order, - // ignoring case when method on element was derived from behavior. - for (var i = element.behaviors.length - 1; i >= 0; i--) { - let behavior = element.behaviors[i]; - let b_method = behavior[name]; - if (!b_method || typeof b_method !== 'function') - continue; - if (b_method == method) - continue; - b_method.apply(element, arguments); - } - }; - - /** - * Constructor a display manager that manages initialization of screens, - * transitions, error messages display. - * - * @constructor - */ - function DisplayManager() { - } - - DisplayManager.prototype = { - /** - * Registered screens. - */ - screens_: [], - - /** - * Attributes of the registered screens. - * @type {Array} - */ - screensAttributes_: [], - - /** - * Current OOBE step, index in the screens array. - * @type {number} - */ - currentStep_: 0, - - /** - * Whether version label can be toggled by ACCELERATOR_VERSION. - * @type {boolean} - */ - allowToggleVersion_: false, - - /** - * Whether keyboard navigation flow is enforced. - * @type {boolean} - */ - forceKeyboardFlow_: false, - - /** - * Whether the virtual keyboard is displayed. - * @type {boolean} - */ - virtualKeyboardShown_: false, - - get virtualKeyboardShown() { - return this.virtualKeyboardShown_; - }, - - set virtualKeyboardShown(shown) { - this.virtualKeyboardShown_ = shown; - document.documentElement.setAttribute('virtual-keyboard', shown); - }, - - /** - * Type of UI. - * @type {string} - */ - displayType_: DISPLAY_TYPE.UNKNOWN, - - /** - * Number of users in the login screen UI. This is used by the views login - * screen, and is always 0 for WebUI login screen. - * TODO(crbug.com/808271): WebUI and views implementation should return the - * same user list. - * @type {number} - */ - userCount_: 0, - - /** - * Stored OOBE configuration for newly registered screens. - * @type {!OobeTypes.OobeConfiguration} - */ - oobe_configuration_: undefined, - - /** - * Detects multi-tap gesture that invokes demo mode setup in OOBE. - * @type {?MultiTapDetector} - * @private - */ - demoModeStartListener_: null, - - /** - * Error message (bubble) was shown. This is checked in tests. - */ - errorMessageWasShownForTesting_: false, - - get displayType() { - return this.displayType_; - }, - - set displayType(displayType) { - this.displayType_ = displayType; - document.documentElement.setAttribute('screen', displayType); - }, - - /** - * Returns dimensions of screen excluding header bar. - * @type {Object} - */ - get clientAreaSize() { - var container = $('outer-container'); - return {width: container.offsetWidth, height: container.offsetHeight}; - }, - - /** - * Gets current screen element. - * @type {HTMLElement} - */ - get currentScreen() { - return $(this.screens_[this.currentStep_]); - }, - - /** - * Returns true if we are showing views based login screen. - * @return {boolean} - */ - get showingViewsLogin() { - return this.displayType_ == DISPLAY_TYPE.GAIA_SIGNIN; - }, - - /** - * Returns true if the login screen has user pods. - * @return {boolean} - */ - get hasUserPods() { - return this.showingViewsLogin && this.userCount_ > 0; - }, - - /** - * Sets the current size of the client area (display size). - * @param {number} width client area width - * @param {number} height client area height - */ - setClientAreaSize: function(width, height) { - if (!cr.isChromeOS) { - var clientArea = $('outer-container'); - var bottom = parseInt(window.getComputedStyle(clientArea).bottom); - clientArea.style.minHeight = cr.ui.toCssPx(height - bottom); - } - }, - - /** - * Sets the current height of the shelf area. - * @param {number} height current shelf height - */ - setShelfHeight: function(height) { - document.documentElement.style.setProperty( - '--shelf-area-height-base', height + 'px'); - }, - - setOrientation: function(isHorizontal) { - if (isHorizontal) { - document.documentElement.setAttribute('orientation', 'horizontal'); - } else { - document.documentElement.setAttribute('orientation', 'vertical'); - } - }, - - setDialogSize: function(width, height) { - document.documentElement.style.setProperty( - '--oobe-oobe-dialog-height-base', height + 'px'); - document.documentElement.style.setProperty( - '--oobe-oobe-dialog-width-base', width + 'px'); - }, - - /** - * Sets the hint for calculating OOBE dialog inner padding. - * @param {OobeTypes.DialogPaddingMode} mode. - */ - setDialogPaddingMode: function(mode) { - document.documentElement.setAttribute('dialog-padding', mode); - }, - - /** - * Toggles background of main body between transparency and solid. - * @param {boolean} solid Whether to show a solid background. - */ - set solidBackground(solid) { - if (solid) - document.body.classList.add('solid'); - else - document.body.classList.remove('solid'); - }, - - /** - * Forces keyboard based OOBE navigation. - * @param {boolean} value True if keyboard navigation flow is forced. - */ - set forceKeyboardFlow(value) { - this.forceKeyboardFlow_ = value; - if (value) { - keyboard.initializeKeyboardFlow(false); - for (var i = 0; i < this.screens_.length; ++i) { - var screen = $(this.screens_[i]); - if (screen.enableKeyboardFlow) - screen.enableKeyboardFlow(); - } - } - }, - - /** - * Returns true if keyboard flow is enabled. - * @return {boolean} - */ - get forceKeyboardFlow() { - return this.forceKeyboardFlow_; - }, - - /** - * Returns current OOBE configuration. - * @return {!OobeTypes.OobeConfiguration} - */ - getOobeConfiguration: function() { - return this.oobe_configuration_; - }, - - /** - * Shows/hides version labels. - * @param {boolean} show Whether labels should be visible by default. If - * false, visibility can be toggled by ACCELERATOR_VERSION. - */ - showVersion: function(show) { - $('version-labels').hidden = !show; - this.allowToggleVersion_ = !show; - }, - - /** - * Sets the number of users on the views login screen. - * @param {number} userCount The number of users. - */ - setLoginUserCount: function(userCount) { - this.userCount_ = userCount; - }, - - /** - * Handle accelerators. - * @param {string} name Accelerator name. - */ - handleAccelerator: function(name) { - if (this.currentScreen && this.currentScreen.ignoreAccelerators) { - return; - } - var currentStepId = this.screens_[this.currentStep_]; - var attributes = this.screensAttributes_[this.currentStep_] || {}; - if (name == ACCELERATOR_CANCEL) { - if (this.currentScreen && this.currentScreen.cancel) { - this.currentScreen.cancel(); - } - } else if (name == ACCELERATOR_VERSION) { - if (this.allowToggleVersion_) - $('version-labels').hidden = !$('version-labels').hidden; - } else if (name == ACCELERATOR_RESET) { - if (currentStepId == SCREEN_OOBE_RESET) { - $('reset').userActed(USER_ACTION_ROLLBACK_TOGGLED); - } else if (attributes.resetAllowed || - RESET_AVAILABLE_SCREEN_GROUP.indexOf(currentStepId) != -1) { - chrome.send('toggleResetScreen'); - } - } else if (name == ACCELERATOR_APP_LAUNCH_BAILOUT) { - if (currentStepId == SCREEN_APP_LAUNCH_SPLASH) - chrome.send('cancelAppLaunch'); - } else if (name == ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG) { - if (currentStepId == SCREEN_APP_LAUNCH_SPLASH) - chrome.send('networkConfigRequest'); - } - }, - - /** - * Appends buttons to the button strip. - * @param {Array} buttons Array with the buttons to append. - * @param {string} screenId Id of the screen that buttons belong to. - */ - appendButtons_: function(buttons, screenId) { - if (buttons) { - var buttonStrip = $(screenId + '-controls'); - if (buttonStrip) { - for (var i = 0; i < buttons.length; ++i) - buttonStrip.appendChild(buttons[i]); - } - } - }, - - /** - * Disables or enables control buttons on the specified screen. - * @param {HTMLElement} screen Screen which controls should be affected. - * @param {boolean} disabled Whether to disable controls. - */ - disableButtons_: function(screen, disabled) { - var buttons = document.querySelectorAll( - '#' + screen.id + '-controls button:not(.preserve-disabled-state)'); - for (var i = 0; i < buttons.length; ++i) { - buttons[i].disabled = disabled; - } - }, - - /** - * Switches to the next OOBE step. - * @param {number} nextStepIndex Index of the next step. - */ - toggleStep_: function(nextStepIndex, screenData) { - var currentStepId = this.screens_[this.currentStep_]; - var nextStepId = this.screens_[nextStepIndex]; - var oldStep = $(currentStepId); - var newStep = $(nextStepId); - var currentStepAttributes = this.screensAttributes_[this.currentStep_] || - {}; - var newStepAttributes = this.screensAttributes_[nextStepIndex] || {}; - - // Disable controls before starting animation. - this.disableButtons_(oldStep, true); - - invokePolymerMethod(oldStep, 'onBeforeHide'); - - if (oldStep.defaultControl) - invokePolymerMethod(oldStep.defaultControl, 'onBeforeHide'); - - $('oobe').className = nextStepId; - - // Need to do this before calling newStep.onBeforeShow() so that new step - // is back in DOM tree and has correct offsetHeight / offsetWidth. - newStep.hidden = false; - - if (newStep.getOobeUIInitialState) { - this.setOobeUIState(newStep.getOobeUIInitialState()); - } else { - this.setOobeUIState(OOBE_UI_STATE.HIDDEN); - } - - invokePolymerMethod(newStep, 'onBeforeShow', screenData); - - // We still have several screens that are not implemented as a single - // Polymer-element, so we need to explicitly inform all oobe-dialogs. - // - // TODO(alemate): make every screen a single Polymer element, so that - // we could simply use OobeDialogHostBehavior in stead of this. - for(let dialog of newStep.getElementsByTagName('oobe-dialog')) - invokePolymerMethod(dialog, 'onBeforeShow', screenData); - - if (newStep.defaultControl) - invokePolymerMethod(newStep.defaultControl, 'onBeforeShow', screenData); - - newStep.classList.remove('hidden'); - - // Start fading animation for login display or reset screen. - oldStep.classList.add('faded'); - newStep.classList.remove('faded'); - - this.disableButtons_(newStep, false); - - // Adjust inner container height based on new step's height. - this.updateScreenSize(newStep); - - // Default control to be focused (if specified). - var defaultControl = newStep.defaultControl; - - var outerContainer = $('outer-container'); - var innerContainer = $('inner-container'); - var isOOBE = this.isOobeUI(); - if (this.currentStep_ != nextStepIndex && - !oldStep.classList.contains('hidden')) { - oldStep.classList.add('hidden'); - oldStep.hidden = true; - if (defaultControl) - defaultControl.focus(); - } else { - // First screen on OOBE launch. - if (this.isOobeUI() && innerContainer.classList.contains('down')) { - innerContainer.classList.remove('down'); - innerContainer.addEventListener('transitionend', function f(e) { - innerContainer.removeEventListener('transitionend', f); - chrome.send('loginVisible', ['oobe']); - // Refresh defaultControl. It could have changed. - var defaultControl = newStep.defaultControl; - if (defaultControl) - defaultControl.focus(); - }); - ensureTransitionEndEvent( - innerContainer, MAX_SCREEN_TRANSITION_DURATION); - } else { - if (defaultControl) - defaultControl.focus(); - chrome.send('loginVisible', ['oobe']); - } - } - this.currentStep_ = nextStepIndex; - - // Call onAfterShow after currentStep_ so that the step can have a - // post-set hook. - invokePolymerMethod(newStep, 'onAfterShow', screenData); - - var stepLogo = $('step-logo'); - if (stepLogo) { - stepLogo.hidden = newStep.classList.contains('no-logo'); - } - - $('oobe').dispatchEvent( - new CustomEvent('screenchanged', {detail: this.currentScreen.id})); - chrome.send('updateCurrentScreen', [this.currentScreen.id]); - }, - - /** - * Make sure that screen is initialized and decorated. - * @param {Object} screen Screen params dict, e.g. {id: screenId, data: {}}. - */ - preloadScreen: function(screen) { - var screenEl = $(screen.id); - if (screenEl.deferredInitialization !== undefined) { - screenEl.deferredInitialization(); - delete screenEl.deferredInitialization; - } - }, - - /** - * Show screen of given screen id. - * @param {Object} screen Screen params dict, e.g. {id: screenId, data: {}}. - */ - showScreen: function(screen) { - // Do not allow any other screen to clobber the device disabled screen. - if (this.currentScreen.id == SCREEN_DEVICE_DISABLED) - return; - - // Prevent initial GAIA signin load from interrupting the kiosk splash - // screen. - // TODO: remove this special case when a better fix is found for the race - // condition. This if statement was introduced to fix http://b/113786350. - if (this.currentScreen.id == SCREEN_APP_LAUNCH_SPLASH && - screen.id == SCREEN_GAIA_SIGNIN) { - console.log( - this.currentScreen.id + - ' screen showing. Ignoring switch to Gaia screen.'); - return; - } - - var screenId = screen.id; - - // Make sure the screen is decorated. - this.preloadScreen(screen); - - var data = screen.data; - var index = this.getScreenIndex_(screenId); - if (index >= 0) - this.toggleStep_(index, data); - }, - - /** - * Gets index of given screen id in screens_. - * @param {string} screenId Id of the screen to look up. - * @private - */ - getScreenIndex_: function(screenId) { - for (let i = 0; i < this.screens_.length; ++i) { - if (this.screens_[i] == screenId) - return i; - } - return -1; - }, - - /** - * Register an oobe screen. - * @param {Element} el Decorated screen element. - * @param {DisplayManagerScreenAttributes} attributes - */ - registerScreen: function(el, attributes) { - var screenId = el.id; - assert(screenId); - assert(!this.screens_.includes(screenId), "Duplicate screen ID."); - - this.screens_.push(screenId); - this.screensAttributes_.push(attributes); - - // No headers on Chrome OS - var headerSections = $('header-sections'); - if (headerSections) { - var header = document.createElement('span'); - header.id = 'header-' + screenId; - header.textContent = el.header ? el.header : ''; - header.className = 'header-section'; - headerSections.appendChild(header); - } - this.appendButtons_(el.buttons, screenId); - - if (el.updateOobeConfiguration && this.oobe_configuration_) - el.updateOobeConfiguration(this.oobe_configuration_); - }, - - /** - * Updates inner container size based on the size of the current screen and - * other screens in the same group. - * Should be executed on screen change / screen size change. - * @param {!HTMLElement} screen Screen that is being shown. - */ - updateScreenSize: function(screen) { - if (!cr.isChromeOS) { - // Have to reset any previously predefined screen size first - // so that screen contents would define it instead. - $('inner-container').style.height = ''; - $('inner-container').style.width = ''; - screen.style.width = ''; - screen.style.height = ''; - } - - $('outer-container').classList.toggle( - 'fullscreen', screen.classList.contains('fullscreen')); - - var width = screen.getPreferredSize().width; - var height = screen.getPreferredSize().height; - - if (!cr.isChromeOS) { - if (screen.classList.contains('fullscreen')) { - $('inner-container').style.height = '100%'; - $('inner-container').style.width = '100%'; - } else { - $('inner-container').style.height = height + 'px'; - $('inner-container').style.width = width + 'px'; - } - // This requires |screen| to have 'box-sizing: border-box'. - screen.style.width = width + 'px'; - screen.style.height = height + 'px'; - screen.style.margin = 'auto'; - } - }, - - /** - * Updates localized content of the screens like headers, buttons and links. - * Should be executed on language change. - */ - updateLocalizedContent_: function() { - for (let i = 0; i < this.screens_.length; ++i) { - let screenId = this.screens_[i]; - var screen = $(screenId); - var buttonStrip = $(screenId + '-controls'); - if (buttonStrip) - buttonStrip.innerHTML = ''; - // TODO(nkostylev): Update screen headers for new OOBE design. - this.appendButtons_(screen.buttons, screenId); - if (screen.updateLocalizedContent) - screen.updateLocalizedContent(); - } - var dynamicElements = document.getElementsByClassName('i18n-dynamic'); - for (var child of dynamicElements) { - if (typeof(child.i18nUpdateLocale) === 'function') { - child.i18nUpdateLocale(); - } - } - var isInTabletMode = loadTimeData.getBoolean('isInTabletMode'); - this.setTabletModeState_(isInTabletMode); - - var currentScreenId = this.screens_[this.currentStep_]; - var currentScreen = $(currentScreenId); - this.updateScreenSize(currentScreen); - }, - - /** - * Updates Oobe configuration for screens. - * @param {!OobeTypes.OobeConfiguration} configuration OOBE configuration. - */ - updateOobeConfiguration_: function(configuration) { - this.oobe_configuration_ = configuration; - for (let i = 0; i < this.screens_.length; ++i) { - let screenId = this.screens_[i]; - var screen = $(screenId); - if (screen.updateOobeConfiguration) - screen.updateOobeConfiguration(configuration); - } - }, - - /** - * Updates "device in tablet mode" state when tablet mode is changed. - * @param {Boolean} isInTabletMode True when in tablet mode. - */ - setTabletModeState_: function(isInTabletMode) { - for (let i = 0; i < this.screens_.length; ++i) { - let screenId = this.screens_[i]; - var screen = $(screenId); - if (screen.setTabletModeState) - screen.setTabletModeState(isInTabletMode); - } - }, - - /** Initializes demo mode start listener. */ - initializeDemoModeMultiTapListener: function() { - if (this.displayType_ == DISPLAY_TYPE.OOBE) { - this.demoModeStartListener_ = new MultiTapDetector( - $('outer-container'), 10, () => { - let currentScreen = Oobe.getInstance().currentScreen; - if (currentScreen.id === SCREEN_WELCOME) { - currentScreen.onSetupDemoModeGesture(); - } - }); - } - }, - - /** - * Prepares screens to use in login display. - */ - prepareForLoginDisplay_: function() { - if (this.showingViewsLogin) { - $('top-header-bar').hidden = true; - } - }, - - /** - * Called when window size changed. Notifies current screen about - * change. - * @private - */ - onWindowResize_: function() { - for (var i = 0, screenId; screenId = this.screens_[i]; ++i) { - var screen = $(screenId); - if (screen.onWindowResize) - screen.onWindowResize(); - } - }, - - /** - * Returns true if Oobe UI is shown. - */ - isOobeUI: function() { - return document.body.classList.contains('oobe-display'); - }, - - /** - * Sets or unsets given |className| for top-level container. Useful - * for customizing #inner-container with CSS rules. All classes set - * with with this method will be removed after screen change. - * @param {string} className Class to toggle. - * @param {boolean} enabled Whether class should be enabled or disabled. - */ - toggleClass: function(className, enabled) { - $('oobe').classList.toggle(className, enabled); - }, - - /** - * Notifies the C++ handler in views login that the OOBE signin state has - * been updated. This information is primarily used by the login shelf to - * update button visibility state. - * @param {number} state The state (see OOBE_UI_STATE) of the OOBE UI. - */ - setOobeUIState: function(state) { - chrome.send('updateOobeUIState', [state]); - }, - - }; - - /** - * Initializes display manager. - */ - DisplayManager.initialize = function() { - var givenDisplayType = DISPLAY_TYPE.UNKNOWN; - if (document.documentElement.hasAttribute('screen')) { - // Display type set in HTML property. - givenDisplayType = document.documentElement.getAttribute('screen'); - } else { - // Extracting display type from URL. - givenDisplayType = window.location.pathname.substr(1); - } - var instance = Oobe.getInstance(); - Object.getOwnPropertyNames(DISPLAY_TYPE).forEach(function(type) { - if (DISPLAY_TYPE[type] == givenDisplayType) { - instance.displayType = givenDisplayType; - } - }); - if (instance.displayType == DISPLAY_TYPE.UNKNOWN) { - console.error( - 'Unknown display type "' + givenDisplayType + - '". Setting default.'); - instance.displayType = DISPLAY_TYPE.LOGIN; - } - - instance.initializeDemoModeMultiTapListener(); - - window.addEventListener('resize', instance.onWindowResize_.bind(instance)); - }; - - /** - * Returns offset (top, left) of the element. - * @param {!Element} element HTML element. - * @return {!Object} The offset (top, left). - */ - DisplayManager.getOffset = function(element) { - var x = 0; - var y = 0; - while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { - x += element.offsetLeft - element.scrollLeft; - y += element.offsetTop - element.scrollTop; - element = element.offsetParent; - } - return { top: y, left: x }; - }; - - /** - * Returns position (top, left, right, bottom) of the element. - * @param {!Element} element HTML element. - * @return {!Object} Element position (top, left, right, bottom). - */ - DisplayManager.getPosition = function(element) { - var offset = DisplayManager.getOffset(element); - return { - top: offset.top, - right: window.innerWidth - element.offsetWidth - offset.left, - bottom: window.innerHeight - element.offsetHeight - offset.top, - left: offset.left - }; - }; - - // Only called from user-manager code, can be removed once desktop is - // migrated to profile-manager UI. - /** - * Disables signin UI. - */ - DisplayManager.disableSigninUI = function() { - if ($('pod-row')) { - $('pod-row').disabled = true; - } - }; - - /** - * Shows signin UI. - * @param {string} opt_email An optional email for signin UI. - */ - DisplayManager.showSigninUI = function(opt_email) { - var currentScreenId = Oobe.getInstance().currentScreen.id; - if (currentScreenId == SCREEN_GAIA_SIGNIN) - Oobe.getInstance().setOobeUIState(OOBE_UI_STATE.GAIA_SIGNIN); - chrome.send('showAddUser', [opt_email]); - }; - - /** - * Resets sign-in input fields. - * @param {boolean} forceOnline Whether online sign-in should be forced. - * If |forceOnline| is false previously used sign-in type will be used. - */ - DisplayManager.resetSigninUI = function(forceOnline) { - var currentScreenId = Oobe.getInstance().currentScreen.id; - - if ($(SCREEN_GAIA_SIGNIN)) { - $(SCREEN_GAIA_SIGNIN) - .reset(currentScreenId == SCREEN_GAIA_SIGNIN, forceOnline); - } - }; - - /** - * Creates a div element used to display error message in an error bubble. - * - * @param {string} message The error message. - * @param {string} link Text to use for help link. - * @param {number} helpId Help topic Id associated with help link. - * @return {!HTMLElement} The error bubble content. - */ - DisplayManager.createErrorElement_ = function(message, link, helpId) { - var error = document.createElement('div'); - - var messageDiv = document.createElement('div'); - messageDiv.className = 'error-message-bubble'; - messageDiv.textContent = message; - error.appendChild(messageDiv); - - if (link) { - messageDiv.classList.add('error-message-bubble-padding'); - - var helpLink = document.createElement('a'); - helpLink.href = '#'; - helpLink.textContent = link; - helpLink.addEventListener('click', function(e) { - chrome.send('launchHelpApp', [helpId]); - e.preventDefault(); - }); - error.appendChild(helpLink); - } - - error.setAttribute('aria-live', 'assertive'); - return error; - }; - - /** - * Shows sign-in error bubble. - * @param {number} loginAttempts Number of login attemps tried. - * @param {string} message Error message to show. - * @param {string} link Text to use for help link. - * @param {number} helpId Help topic Id associated with help link. - */ - DisplayManager.showSignInError = function( - loginAttempts, message, link, helpId) { - var error = DisplayManager.createErrorElement_(message, link, helpId); - - var currentScreen = Oobe.getInstance().currentScreen; - if (currentScreen && typeof currentScreen.showErrorBubble === 'function') { - currentScreen.showErrorBubble(loginAttempts, error); - this.errorMessageWasShownForTesting_ = true; - } - }; - - /** - * Clears error bubble. - */ - DisplayManager.clearErrors = function() { - $('bubble').hide(); - this.errorMessageWasShownForTesting_ = false; - - var bubbles = document.querySelectorAll('.bubble-shown'); - for (var i = 0; i < bubbles.length; ++i) - bubbles[i].classList.remove('bubble-shown'); - }; - - /** - * Sets text content for a div with |labelId|. - * @param {string} labelId Id of the label div. - * @param {string} labelText Text for the label. - */ - DisplayManager.setLabelText = function(labelId, labelText) { - $(labelId).textContent = labelText; - }; - - /** - * Sets the text content of the enterprise info message and asset ID. - * @param {string} messageText The message text. - * @param {string} assetId The device asset ID. - */ - DisplayManager.setEnterpriseInfo = function(messageText, assetId) { - $('asset-id').textContent = - ((assetId == '') ? '' : - loadTimeData.getStringF('assetIdLabel', assetId)); - }; - - /** - * Sets the text content of the Bluetooth device info message. - * @param {string} bluetoothName The Bluetooth device name text. - */ - DisplayManager.setBluetoothDeviceInfo = function(bluetoothName) { - $('bluetooth-name').hidden = false; - $('bluetooth-name').textContent = bluetoothName; - }; - - // Export - return { - DisplayManager: DisplayManager, - invokePolymerMethod: invokePolymerMethod, - }; -}); diff --git a/chromium/ui/login/display_manager_types.js b/chromium/ui/login/display_manager_types.js deleted file mode 100644 index d7f8085e127..00000000000 --- a/chromium/ui/login/display_manager_types.js +++ /dev/null @@ -1,73 +0,0 @@ -// 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. - -/** - * @fileoverview - * Closure compiler type definitions used by display_manager.js . - */ - -/** - * @typedef {{ - * resetAllowed: (boolean|undefined), - * }} - */ -var DisplayManagerScreenAttributes = {}; - -/** - * True if device reset is allowed on the screen. - * @type {boolean|undefined} - */ -DisplayManagerScreenAttributes.resetAllowed; - -/** - * Possible types of UI. - * @enum {string} - */ -var DISPLAY_TYPE = { - UNKNOWN: 'unknown', - OOBE: 'oobe', - LOGIN: 'login', - LOCK: 'lock', - APP_LAUNCH_SPLASH: 'app-launch-splash', - DESKTOP_USER_MANAGER: 'login-add-user', - GAIA_SIGNIN: 'gaia-signin' -}; - -/** - * Oobe UI state constants. - * Used to control native UI elements. - * Should be in sync with login_types.h - * @enum {number} - */ -var OOBE_UI_STATE = { - HIDDEN: 0, /* Any OOBE screen without specific state */ - GAIA_SIGNIN: 1, - ACCOUNT_PICKER: 2, - WRONG_HWID_WARNING: 3, - DEPRECATED_SUPERVISED_USER_CREATION_FLOW: 4, - SAML_PASSWORD_CONFIRM: 5, - PASSWORD_CHANGED: 6, - ENROLLMENT: 7, - ERROR: 8, - ONBOARDING: 9, - BLOCKING: 10, - KIOSK: 11, - MIGRATION: 12, - USER_CREATION: 15, -}; - -/** - * Possible UI states of the error screen. - * @enum {string} - */ -var ERROR_SCREEN_UI_STATE = { - UNKNOWN: 'ui-state-unknown', - UPDATE: 'ui-state-update', - SIGNIN: 'ui-state-signin', - KIOSK_MODE: 'ui-state-kiosk-mode', - LOCAL_STATE_ERROR: 'ui-state-local-state-error', - AUTO_ENROLLMENT_ERROR: 'ui-state-auto-enrollment-error', - ROLLBACK_ERROR: 'ui-state-rollback-error', - SUPERVISED_USER_CREATION_FLOW: 'ui-state-supervised', -}; diff --git a/chromium/ui/login/login_ui_tools.js b/chromium/ui/login/login_ui_tools.js deleted file mode 100644 index 66ed2686bf0..00000000000 --- a/chromium/ui/login/login_ui_tools.js +++ /dev/null @@ -1,58 +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. - -/** - * @fileoverview JS helpers used on login. - */ - -cr.define('cr.ui.LoginUITools', function() { - return { - /** - * Computes max-height for an element so that it doesn't overlap shelf. - * @param {Element} element DOM element - * @param {boolean} wholeWindow Whether the element can go outside - * outer-container. - */ - getMaxHeightBeforeShelfOverlapping : function(element, wholeWindow) { - var maxAllowedHeight = - $('outer-container').offsetHeight - - element.getBoundingClientRect().top - - parseInt(window.getComputedStyle(element).marginTop, 10) - - parseInt(window.getComputedStyle(element).marginBottom, 10); - if (wholeWindow) { - maxAllowedHeight += - parseInt(window.getComputedStyle($('outer-container')).bottom, 10); - } - return maxAllowedHeight; - }, - - /** - * Computes max-width for an element so that it does fit the - * outer-container. - * @param {Element} element DOM element - */ - getMaxWidthToFit : function(element) { - var maxAllowedWidth = - $('outer-container').offsetWidth - - element.getBoundingClientRect().left - - parseInt(window.getComputedStyle(element).marginLeft, 10) - - parseInt(window.getComputedStyle(element).marginRight, 10); - return maxAllowedWidth; - }, - - /** - * Listens to key events on input element. - * @param {Element} element DOM element - * @param {Object} callback - */ - addSubmitListener : function(element, callback) { - element.addEventListener('keydown', (function(callback, e) { - if (e.keyCode != 13) - return; - callback(); - }).bind(undefined, callback)); - }, - } - -}); diff --git a/chromium/ui/login/oobe.css b/chromium/ui/login/oobe.css deleted file mode 100644 index c8ef82e699d..00000000000 --- a/chromium/ui/login/oobe.css +++ /dev/null @@ -1,197 +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. - * - * This is the stylesheet used by the Out of the box experience (OOBE) flow, - * sign in and lock screens. - */ - -:root { - --google-grey-700: rgb(95, 99, 104); - --shelf-area-height-base: 57px; - --oobe-oobe-dialog-height-base: 504px; - --oobe-oobe-dialog-width-base: 461px; -} - -html, -body { - height: 100%; - width: 100%; -} - -html { - --shelf-area-height: var(--shelf-area-height-base); -} - -html[virtual-keyboard=true], -html[screen=gaia-signin] { - /* has to be with px suffix to be used in calc */ - --shelf-area-height: 0px; -} - -body { - background-color: transparent; - cursor: default; - font-size: 14px; - margin: 0; - overflow: hidden; - padding: 0; - position: fixed; - top: 0; -} - -/* Keep full-screen white background even when user signs into session after - * oobe */ -html[screen=oobe] body { - background-color: white; -} - -/* New dialog size */ -html { - --oobe-adaptive-dialog-width: var(--oobe-oobe-dialog-width-base); - --oobe-adaptive-dialog-height: var(--oobe-oobe-dialog-height-base); -} - -/* Padding defaults */ -html { - --oobe-dialog-footer-height: 96px; - --oobe-dialog-footer-padding: 32px; - --oobe-dialog-content-padding: 64px; - --oobe-dialog-content-padding-top: 20px; - --oobe-dialog-header-padding-top: 64px; - - /* This size fits 675px screen with docked magnifier and shelf. Basically this - * is calc(675px * (1 - 1 / 3) - 10px - var(--shelf-area-height-base)) where - * 3 is DockedMagnifierControllerImpl::kScreenHeightDivisor - * 10 is DockedMagnifierControllerImpl::kSeparatorHeight */ - --oobe-dialog-min-height: 384px; - - --oobe-dialog-side-margin: 48px; - - --oobe-dialog-adaptable-flex-direction: column; - - --oobe-forward-slide-animation: translateX(+100%); - --oobe-backward-slide-animation: translateX(-100%); -} - -html[dir=rtl] { - --oobe-forward-slide-animation: translateX(-100%); - --oobe-backward-slide-animation: translateX(+100%); -} - -html[screen=gaia-signin] { - /* has to be with px suffix to be used in calc */ - --oobe-dialog-side-margin: 0px; -} - - -@media screen and (max-width: 864px), (max-height: 736px) { - html[screen=oobe] { - --oobe-dialog-footer-height: 80px; - --oobe-dialog-footer-padding: 24px; - --oobe-dialog-content-padding: 32px; - --oobe-dialog-header-padding-top: 32px; - } -} - -/* Adapt for horizontal screen */ -@media screen and (min-width: 768px) and (max-height: 768px) { - html[screen=oobe] { - --oobe-dialog-adaptable-flex-direction: row; - } -} - -/* Adapt for horizontal screen. 616px - corresponding height of the OOBE dialog - * for gaia-signin flow when screen height is 768px */ -@media screen and (min-width: 616px) and (max-height: 616px) { - html[screen=gaia-signin] { - --oobe-dialog-adaptable-flex-direction: row; - } -} - -html[screen=gaia-signin][dialog-padding=narrow] { - --oobe-dialog-footer-height: 80px; - --oobe-dialog-footer-padding: 24px; - --oobe-dialog-content-padding: 32px; - --oobe-dialog-header-padding-top: 32px; -} - -body.solid { - background-color: white; -} - -button { - font-family: inherit; - outline: none; -} - -.label, -.flexible-label { - display: block; - margin: 5px 5px 5px 0; - padding: 5px 5px 5px 0; -} - -.label { - width: 170px; -} - -.flexible-label { - max-width: 250px; -} - -[hidden] { - display: none !important; -} - -#bubble { - transition: 250ms opacity; -} - -span.bold { - font-weight: bold; -} - -#version-labels { - color: var(--google-grey-700); - font-size: 13px; - margin: 10px; - position: relative; - text-align: end; - transition: all 500ms linear; - z-index: 1; -} - -#bluetooth-name { - background: rgba(255,255,255,.17); - border-radius: 4px; - display: inline-block; - font-size: 12px; - height: 28px; - line-height: 28px; - padding: 0 12px; -} - -#background { - background-size: 100% 100%; - height: 100%; - left: 0; - position: absolute; - top: 0; - transition: 700ms opacity; - width: 100%; -} - -.background-initial { - opacity: 0; -} - -.dimmed-background { - background-color: black; - opacity: 0.5; -} - -.throbber { - -webkit-margin-end: 0.5em; - margin-top: 1px; -} diff --git a/chromium/ui/login/screen.js b/chromium/ui/login/screen.js deleted file mode 100644 index 8d1263b41d1..00000000000 --- a/chromium/ui/login/screen.js +++ /dev/null @@ -1,212 +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. - -/** - * @fileoverview Base class for all login WebUI screens. - */ -cr.define('login', function() { - /** @const */ var CALLBACK_USER_ACTED = 'userActed'; - - function doNothing() {}; - - function alwaysTruePredicate() { return true; } - - var querySelectorAll = HTMLDivElement.prototype.querySelectorAll; - - var Screen = function(sendPrefix) { - this.sendPrefix_ = sendPrefix; - }; - - Screen.prototype = { - __proto__: HTMLDivElement.prototype, - - /** - * Prefix added to sent to Chrome messages' names. - */ - sendPrefix_: null, - - /** - * Called during screen initialization. - */ - decorate: doNothing, - - /** - * Returns minimal size that screen prefers to have. Default implementation - * returns current screen size. - * @return {{width: number, height: number}} - */ - getPreferredSize: function() { - return {width: this.offsetWidth, height: this.offsetHeight}; - }, - - /** - * Called for currently active screen when screen size changed. - */ - onWindowResize: doNothing, - - /** - * @final - */ - initialize: function() { - return this.initializeImpl_.apply(this, arguments); - }, - - /** - * @final - */ - send: function() { - return this.sendImpl_.apply(this, arguments); - }, - - /** - * @override - * @final - */ - querySelectorAll: function() { - return this.querySelectorAllImpl_.apply(this, arguments); - }, - - /** - * @private - */ - initializeImpl_: function() { - this.decorate(); - }, - - /** - * Sends message to Chrome, adding needed prefix to message name. All - * arguments after |messageName| are packed into message parameters list. - * - * @param {string} messageName Name of message without a prefix. - * @param {...*} varArgs parameters for message. - * @private - */ - sendImpl_: function(messageName, varArgs) { - if (arguments.length == 0) - throw Error('Message name is not provided.'); - var fullMessageName = this.sendPrefix_ + messageName; - var payload = Array.prototype.slice.call(arguments, 1); - chrome.send(fullMessageName, payload); - }, - - /** - * Calls standart |querySelectorAll| method and returns its result converted - * to Array. - * @private - */ - querySelectorAllImpl_: function(selector) { - var list = querySelectorAll.call(this, selector); - return Array.prototype.slice.call(list); - }, - - /** - * If |value| is the value of some property of |this| returns property's - * name. Otherwise returns empty string. - * @private - */ - getPropertyNameOf_: function(value) { - for (var key in this) - if (this[key] === value) - return key; - return ''; - } - }; - - Screen.CALLBACK_USER_ACTED = CALLBACK_USER_ACTED; - - return { - Screen: Screen - }; -}); - -cr.define('login', function() { - return { - /** - * Creates class and object for screen. - * Methods specified in EXTERNAL_API array of prototype - * will be available from C++ part. - * Example: - * login.createScreen('ScreenName', 'screen-id', { - * foo: function() { console.log('foo'); }, - * bar: function() { console.log('bar'); } - * EXTERNAL_API: ['foo']; - * }); - * login.ScreenName.register(); - * var screen = $('screen-id'); - * screen.foo(); // valid - * login.ScreenName.foo(); // valid - * screen.bar(); // valid - * login.ScreenName.bar(); // invalid - * - * @param {string} name Name of created class. - * @param {string} id Id of div representing screen. - * @param {(function()|Object)} proto Prototype of object or function that - * returns prototype. - */ - createScreen: function(name, id, template, attributes) { - if (typeof template == 'function') - template = template(); - - var apiNames = template.EXTERNAL_API || []; - for (var i = 0; i < apiNames.length; ++i) { - var methodName = apiNames[i]; - if (typeof template[methodName] !== 'function') - throw Error('External method "' + methodName + '" for screen "' + - name + '" not a function or undefined.'); - } - - function checkPropertyAllowed(propertyName) { - if (propertyName.charAt(propertyName.length - 1) === '_' && - (propertyName in login.Screen.prototype)) { - throw Error('Property "' + propertyName + '" of "' + id + '" ' + - 'shadows private property of login.Screen prototype.'); - } - }; - - var Constructor = function() { - login.Screen.call(this, 'login.' + name + '.'); - }; - Constructor.prototype = Object.create(login.Screen.prototype); - var api = {}; - - Object.getOwnPropertyNames(template).forEach(function(propertyName) { - if (propertyName === 'EXTERNAL_API') - return; - - checkPropertyAllowed(propertyName); - - var descriptor = - Object.getOwnPropertyDescriptor(template, propertyName); - Object.defineProperty(Constructor.prototype, propertyName, descriptor); - - if (apiNames.indexOf(propertyName) >= 0) { - api[propertyName] = function() { - var screen = $(id); - return screen[propertyName].apply(screen, arguments); - }; - } - }); - - Constructor.prototype.name = function() { return id; }; - - api.register = function(opt_lazy_init) { - var screen = $(id); - screen.__proto__ = new Constructor(); - - if (opt_lazy_init !== undefined && opt_lazy_init) - screen.deferredInitialization = function() { screen.initialize(); } - else - screen.initialize(); - Oobe.getInstance().registerScreen(screen, attributes); - }; - - // See also c/b/r/chromeos/login/login_screen_behavior.js - cr.define('login', function() { - var result = {}; - result[name] = api; - return result; - }); - } - }; -}); diff --git a/chromium/ui/login/screen_container.css b/chromium/ui/login/screen_container.css deleted file mode 100644 index b16ec265c40..00000000000 --- a/chromium/ui/login/screen_container.css +++ /dev/null @@ -1,147 +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. - */ - -#outer-container { - -webkit-box-align: center; - -webkit-box-pack: center; - bottom: var(--shelf-area-height); /* Leave space for the header bar */ - display: -webkit-box; - left: 0; - min-height: 717px; /* This enables scrolling. Min resolution: 1024x768 */ - perspective: 1px; /* Workaround, see http://crbug.com/360567 */ - position: absolute; - right: 0; - top: 0; - z-index: 1; -} - -.oobe-display #outer-container { - bottom: 47px; /* header-bar is 47 pixels high during OOBE */ - perspective: 600px; -} - -.pin-container.pin-enabled { - opacity: 1; - transition: opacity 200ms ease-in-out 180ms; - visibility: visible; -} - -.pin-container.pin-disabled { - opacity: 0; /* Opacity is set to 1 after the pin element is loaded. */ - transition: none; - visibility: hidden; /* Needed because pin-keyboard's offsetHeight is - checked to determine if loaded. */ -} - -#scroll-container { - bottom: 0; /* Allows content overlap with control bar. */ - left: 0; - overflow-x: hidden; - overflow-y: auto; - position: absolute; - right: 0; - top: 0; -} - -#scroll-container::-webkit-scrollbar { - display: none; -} - -#inner-container { - border-radius: 2px; - position: relative; -} - -#inner-container.animation { - overflow: hidden; -} - -#inner-container.disabled { - opacity: 0.4; - pointer-events: none; -} - -/* Screens that have a border and background. */ -#oobe.auto-enrollment-check #inner-container, -#oobe.autolaunch #inner-container, -#oobe.saml-confirm-password #inner-container, -#oobe.debugging #inner-container, -#oobe.enrollment #inner-container, -#oobe.fatal-error #inner-container, -#oobe.gaia-signin #inner-container, -#oobe.hid-detection #inner-container, -#oobe.kiosk-enable #inner-container, -#oobe.enterprise-enrollment #inner-container, -#oobe.password-changed #inner-container, -#oobe.ad-password-change #inner-container, -#oobe.supervised-user-creation #inner-container, -#oobe.supervised-user-creation-dialog #inner-container, -#oobe.terms-of-service #inner-container, -#oobe.arc-tos #inner-container, -#oobe.oobe-update #inner-container, -#oobe.update-required #inner-container, -#oobe.user-image #inner-container, -#oobe.wrong-hwid #inner-container, -#oobe.unrecoverable-cryptohome-error #inner-container { - background: white; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3), - 0 4px 23px 5px rgba(0, 0, 0, 0.2), - 0 2px 6px rgba(0, 0, 0, 0.15); -} - -#oobe.error-message #inner-container, -#oobe.tpm-error-message #inner-container { - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3), - 0 4px 23px 5px rgba(0, 0, 0, 0.2), - 0 2px 6px rgba(0, 0, 0, 0.15); - -} - -/* Only play this animation when 'down' class is removed. */ -.oobe-display #inner-container:not(.down) { - transition: transform 200ms ease-in-out; -} - -.oobe-display #inner-container.down { - transform: translateY(50px) rotateX(-2.5deg); -} - -body:not(.oobe-display) #inner-container { - height: 262px; - padding: 0; - width: 1100px; -} - -#outer-container.fullscreen, -#outer-container.fullscreen #oobe, -#outer-container.fullscreen #oobe #inner-container { - height: 100%; - width: 100%; -} - -html[build=chrome] #header-sections { - -webkit-margin-start: -48px; - margin-top: -1px; -} - -html[build=chromium] #header-sections { - -webkit-margin-start: 5px; - margin-top: -1px; -} - -.header-section { - color: rgb(119, 120, 123); /* Should matching text color of the logo. */ - display: none; - font-size: 23px; - line-height: 31px; - text-transform: lowercase; - width: 23em; -} - -.header-section::before { - /* Divider in header between product name and title, - * like "[Product name] > [step header]". */ - content: '\00A0\203A\00A0\00A0'; -} diff --git a/chromium/ui/message_center/BUILD.gn b/chromium/ui/message_center/BUILD.gn index e04e7642da3..807e24d9bba 100644 --- a/chromium/ui/message_center/BUILD.gn +++ b/chromium/ui/message_center/BUILD.gn @@ -188,6 +188,7 @@ if (enable_message_center) { "//ui/gl", "//ui/gl:test_support", "//ui/message_center/public/cpp", + "//ui/native_theme", "//ui/resources", "//ui/resources:ui_test_pak", "//url", diff --git a/chromium/ui/message_center/fake_message_center.cc b/chromium/ui/message_center/fake_message_center.cc index 40cc51e944c..f54e450875b 100644 --- a/chromium/ui/message_center/fake_message_center.cc +++ b/chromium/ui/message_center/fake_message_center.cc @@ -133,7 +133,7 @@ void FakeMessageCenter::ClickOnNotificationButton(const std::string& id, void FakeMessageCenter::ClickOnNotificationButtonWithReply( const std::string& id, int button_index, - const base::string16& reply) {} + const std::u16string& reply) {} void FakeMessageCenter::ClickOnSettingsButton(const std::string& id) {} @@ -171,12 +171,12 @@ void FakeMessageCenter::RestartPopupTimers() {} void FakeMessageCenter::PausePopupTimers() {} -const base::string16& FakeMessageCenter::GetSystemNotificationAppName() const { +const std::u16string& FakeMessageCenter::GetSystemNotificationAppName() const { return base::EmptyString16(); } void FakeMessageCenter::SetSystemNotificationAppName( - const base::string16& product_os_name) {} + const std::u16string& product_os_name) {} void FakeMessageCenter::DisableTimersForTest() {} diff --git a/chromium/ui/message_center/fake_message_center.h b/chromium/ui/message_center/fake_message_center.h index dcff4734b95..5fa37e41670 100644 --- a/chromium/ui/message_center/fake_message_center.h +++ b/chromium/ui/message_center/fake_message_center.h @@ -58,7 +58,7 @@ class FakeMessageCenter : public MessageCenter { int button_index) override; void ClickOnNotificationButtonWithReply(const std::string& id, int button_index, - const base::string16& reply) override; + const std::u16string& reply) override; void ClickOnSettingsButton(const std::string& id) override; void DisableNotification(const std::string& id) override; void MarkSinglePopupAsShown(const std::string& id, @@ -74,8 +74,8 @@ class FakeMessageCenter : public MessageCenter { bool HasMessageCenterView() const override; void RestartPopupTimers() override; void PausePopupTimers() override; - const base::string16& GetSystemNotificationAppName() const override; - void SetSystemNotificationAppName(const base::string16& name) override; + const std::u16string& GetSystemNotificationAppName() const override; + void SetSystemNotificationAppName(const std::u16string& name) override; protected: void DisableTimersForTest() override; diff --git a/chromium/ui/message_center/message_center.h b/chromium/ui/message_center/message_center.h index 55f11c2ca96..412fba28f5b 100644 --- a/chromium/ui/message_center/message_center.h +++ b/chromium/ui/message_center/message_center.h @@ -146,7 +146,7 @@ class MESSAGE_CENTER_EXPORT MessageCenter { virtual void ClickOnNotificationButtonWithReply( const std::string& id, int button_index, - const base::string16& reply) = 0; + const std::u16string& reply) = 0; // Called by the UI classes when the settings buttons is clicked // to trigger the notification's delegate and update the message @@ -208,8 +208,8 @@ class MESSAGE_CENTER_EXPORT MessageCenter { // used to identify the application that generated a notification. Only used // for MD style notifications, which means that currently it's only set and // used on Chrome OS. On Chrome OS, this is "Chrome OS". - virtual const base::string16& GetSystemNotificationAppName() const = 0; - virtual void SetSystemNotificationAppName(const base::string16& name) = 0; + virtual const std::u16string& GetSystemNotificationAppName() const = 0; + virtual void SetSystemNotificationAppName(const std::u16string& name) = 0; protected: friend class ::DownloadNotification; diff --git a/chromium/ui/message_center/message_center_impl.cc b/chromium/ui/message_center/message_center_impl.cc index bbf6aa269dc..705acbc73fe 100644 --- a/chromium/ui/message_center/message_center_impl.cc +++ b/chromium/ui/message_center/message_center_impl.cc @@ -357,7 +357,7 @@ void MessageCenterImpl::ClickOnNotificationButton(const std::string& id, void MessageCenterImpl::ClickOnNotificationButtonWithReply( const std::string& id, int button_index, - const base::string16& reply) { + const std::u16string& reply) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!FindVisibleNotificationById(id)) return; @@ -371,7 +371,7 @@ void MessageCenterImpl::ClickOnNotificationButtonWithReply( void MessageCenterImpl::ClickOnNotificationUnlocked( const std::string& id, const base::Optional& button_index, - const base::Optional& reply) { + const base::Optional& reply) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // This method must be called under unlocked screen. @@ -498,12 +498,12 @@ void MessageCenterImpl::PausePopupTimers() { popup_timers_controller_->PauseAll(); } -const base::string16& MessageCenterImpl::GetSystemNotificationAppName() const { +const std::u16string& MessageCenterImpl::GetSystemNotificationAppName() const { return system_notification_app_name_; } void MessageCenterImpl::SetSystemNotificationAppName( - const base::string16& name) { + const std::u16string& name) { system_notification_app_name_ = name; } diff --git a/chromium/ui/message_center/message_center_impl.h b/chromium/ui/message_center/message_center_impl.h index 1a0efc9b9e6..47e62d138c6 100644 --- a/chromium/ui/message_center/message_center_impl.h +++ b/chromium/ui/message_center/message_center_impl.h @@ -72,7 +72,7 @@ class MessageCenterImpl : public MessageCenter, int button_index) override; void ClickOnNotificationButtonWithReply(const std::string& id, int button_index, - const base::string16& reply) override; + const std::u16string& reply) override; void ClickOnSettingsButton(const std::string& id) override; void DisableNotification(const std::string& id) override; void MarkSinglePopupAsShown(const std::string& id, @@ -84,8 +84,8 @@ class MessageCenterImpl : public MessageCenter, void EnterQuietModeWithExpire(const base::TimeDelta& expires_in) override; void RestartPopupTimers() override; void PausePopupTimers() override; - const base::string16& GetSystemNotificationAppName() const override; - void SetSystemNotificationAppName(const base::string16& name) override; + const std::u16string& GetSystemNotificationAppName() const override; + void SetSystemNotificationAppName(const std::u16string& name) override; // NotificationBlocker::Observer overrides: void OnBlockingStateChanged(NotificationBlocker* blocker) override; @@ -105,7 +105,7 @@ class MessageCenterImpl : public MessageCenter, void ClickOnNotificationUnlocked(const std::string& id, const base::Optional& button_index, - const base::Optional& reply); + const base::Optional& reply); const std::unique_ptr lock_screen_controller_; @@ -120,7 +120,7 @@ class MessageCenterImpl : public MessageCenter, bool has_message_center_view_ = true; bool spoken_feedback_enabled_ = false; - base::string16 system_notification_app_name_; + std::u16string system_notification_app_name_; MessageCenterStatsCollector stats_collector_; diff --git a/chromium/ui/message_center/message_center_impl_unittest.cc b/chromium/ui/message_center/message_center_impl_unittest.cc index 39a383a432a..7fe22bc51ca 100644 --- a/chromium/ui/message_center/message_center_impl_unittest.cc +++ b/chromium/ui/message_center/message_center_impl_unittest.cc @@ -115,7 +115,7 @@ class TestDelegate : public NotificationDelegate { log_ += (by_user ? "by_user_" : "programmatically_"); } void Click(const base::Optional& button_index, - const base::Optional& reply) override { + const base::Optional& reply) override { if (button_index) { if (!reply) { log_ += "ButtonClick_"; @@ -151,7 +151,7 @@ class DeleteOnCloseDelegate : public NotificationDelegate { message_center_->RemoveNotification(notification_id_, false /* by_user */); } void Click(const base::Optional& button_index, - const base::Optional& reply) override {} + const base::Optional& reply) override {} private: ~DeleteOnCloseDelegate() override = default; @@ -235,11 +235,11 @@ class MessageCenterImplTest : public testing::Test { NotificationType type, scoped_refptr delegate) { RichNotificationData optional_fields; - optional_fields.buttons.emplace_back(UTF8ToUTF16("foo")); - optional_fields.buttons.emplace_back(UTF8ToUTF16("foo")); + optional_fields.buttons.emplace_back(u"foo"); + optional_fields.buttons.emplace_back(u"foo"); return std::make_unique( - type, id, UTF8ToUTF16("title"), UTF8ToUTF16(id), - gfx::Image() /* icon */, base::string16() /* display_source */, GURL(), + type, id, u"title", UTF8ToUTF16(id), gfx::Image() /* icon */, + std::u16string() /* display_source */, GURL(), NotifierId(NotifierType::APPLICATION, notifier_id), optional_fields, delegate); } @@ -473,10 +473,9 @@ TEST_F(MessageCenterImplTest, PopupTimersControllerRestartOnUpdate) { NotifierId notifier_id(GURL("https://example.com")); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); std::unique_ptr popup_timers_controller = std::make_unique(message_center(), closure()); @@ -549,15 +548,13 @@ TEST_F(MessageCenterImplTest, NotificationBlocker) { ToggledNotificationBlocker blocker2(message_center()); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); EXPECT_EQ(2u, message_center()->GetPopupNotifications().size()); EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); @@ -602,10 +599,9 @@ TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) { ToggledNotificationBlocker blocker(message_center()); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); EXPECT_EQ(1u, message_center()->GetPopupNotifications().size()); EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size()); @@ -615,10 +611,9 @@ TEST_F(MessageCenterImplTest, NotificationsDuringBlocked) { // Create a notification during blocked. Still no popups. blocker.SetPopupNotificationsEnabled(false); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); EXPECT_TRUE(message_center()->GetPopupNotifications().empty()); EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); @@ -637,10 +632,9 @@ TEST_F(MessageCenterImplTest, GetNotifications) { // Create a notification without any blockers. message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); EXPECT_EQ(1u, message_center()->GetPopupNotifications().size()); EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size()); EXPECT_EQ(1u, message_center()->GetNotifications().size()); @@ -648,10 +642,9 @@ TEST_F(MessageCenterImplTest, GetNotifications) { // Create a notification while blocking popup notifications. blocker.SetPopupNotificationsEnabled(false); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); EXPECT_EQ(0u, message_center()->GetPopupNotifications().size()); EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); EXPECT_EQ(2u, message_center()->GetNotifications().size()); @@ -659,10 +652,9 @@ TEST_F(MessageCenterImplTest, GetNotifications) { // Create a notification while any notification is blocked. blocker.SetNotificationsEnabled(false); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id, RichNotificationData(), nullptr)); EXPECT_EQ(0u, message_center()->GetPopupNotifications().size()); EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size()); EXPECT_EQ(3u, message_center()->GetNotifications().size()); @@ -688,15 +680,13 @@ TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) { PopupNotificationBlocker blocker(message_center(), notifier_id2); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr)); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr)); // "id1" is displayed as a pop-up so that it will be closed when blocked. message_center()->DisplayedNotification("id1", DISPLAY_SOURCE_POPUP); @@ -710,15 +700,13 @@ TEST_F(MessageCenterImplTest, NotificationBlockerAllowsPopups) { EXPECT_EQ(2u, message_center()->GetVisibleNotifications().size()); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr)); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id4", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id4", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr)); popups = message_center()->GetPopupNotifications(); EXPECT_EQ(2u, popups.size()); EXPECT_TRUE(PopupNotificationsContain(popups, "id2")); @@ -743,15 +731,13 @@ TEST_F(MessageCenterImplTest, TotalNotificationBlocker) { TotalNotificationBlocker blocker(message_center(), notifier_id2); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr)); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr)); // "id1" becomes invisible while "id2" is still visible. blocker.SetPopupNotificationsEnabled(false); @@ -762,15 +748,13 @@ TEST_F(MessageCenterImplTest, TotalNotificationBlocker) { EXPECT_TRUE(NotificationsContain(notifications, "id2")); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr)); message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id4", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id4", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr)); EXPECT_EQ(2u, message_center()->NotificationCount()); notifications = message_center()->GetVisibleNotifications(); EXPECT_FALSE(NotificationsContain(notifications, "id1")); @@ -815,17 +799,15 @@ TEST_F(MessageCenterImplTest, RemoveAllNotifications) { // Notification 1: Visible, non-pinned message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr)); // Notification 2: Invisible, non-pinned message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr)); // Remove all the notifications which are visible and non-pinned. message_center()->RemoveAllNotifications( @@ -853,33 +835,29 @@ TEST_F(MessageCenterImplTest, RemoveAllNotificationsWithPinned) { // Notification 1: Visible, non-pinned message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id1", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr)); // Notification 2: Invisible, non-pinned message_center()->AddNotification(std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id2", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr)); // Notification 3: Visible, pinned auto notification3 = std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id1, - RichNotificationData(), nullptr); + NOTIFICATION_TYPE_SIMPLE, "id3", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id1, RichNotificationData(), nullptr); notification3->set_pinned(true); message_center()->AddNotification(std::move(notification3)); // Notification 4: Invisible, pinned auto notification4 = std::make_unique( - NOTIFICATION_TYPE_SIMPLE, "id4", UTF8ToUTF16("title"), - UTF8ToUTF16("message"), gfx::Image() /* icon */, - base::string16() /* display_source */, GURL(), notifier_id2, - RichNotificationData(), nullptr); + NOTIFICATION_TYPE_SIMPLE, "id4", u"title", u"message", + gfx::Image() /* icon */, std::u16string() /* display_source */, GURL(), + notifier_id2, RichNotificationData(), nullptr); notification4->set_pinned(true); message_center()->AddNotification(std::move(notification4)); @@ -1160,7 +1138,7 @@ TEST_F(MessageCenterImplTest, UpdateNonProgressNotificationWhenCenterVisible) { message_center()->ClickOnNotification("n"); message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); observer.reset_logs(); - notification_copy.set_title(base::ASCIIToUTF16("title2")); + notification_copy.set_title(u"title2"); message_center()->UpdateNotification( notification_copy.id(), std::make_unique(notification_copy)); @@ -1223,8 +1201,7 @@ TEST_F(MessageCenterImplTest, ButtonClickWithReply) { std::unique_ptr notification = CreateSimpleNotification(id); message_center()->AddNotification(std::move(notification)); - message_center()->ClickOnNotificationButtonWithReply( - id, 1, base::UTF8ToUTF16("REPLYTEXT")); + message_center()->ClickOnNotificationButtonWithReply(id, 1, u"REPLYTEXT"); EXPECT_EQ("ReplyButtonClick_1_REPLYTEXT_", GetDelegate(id)->log()); } @@ -1328,8 +1305,7 @@ TEST_F(MessageCenterImplTest, ButtonClickWithReplyOnLockScreen) { std::unique_ptr notification = CreateSimpleNotification(id); message_center()->AddNotification(std::move(notification)); - message_center()->ClickOnNotificationButtonWithReply( - id, 1, base::UTF8ToUTF16("REPLYTEXT")); + message_center()->ClickOnNotificationButtonWithReply(id, 1, u"REPLYTEXT"); EXPECT_EQ("", GetDelegate(id)->log()); EXPECT_TRUE(lock_screen_controller()->HasPendingCallback()); diff --git a/chromium/ui/message_center/message_center_observer.h b/chromium/ui/message_center/message_center_observer.h index f8d249af35f..32d4e6c764c 100644 --- a/chromium/ui/message_center/message_center_observer.h +++ b/chromium/ui/message_center/message_center_observer.h @@ -9,7 +9,6 @@ #include "base/observer_list_types.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/message_center_types.h" @@ -42,7 +41,7 @@ class MESSAGE_CENTER_EXPORT MessageCenterObserver virtual void OnNotificationClicked( const std::string& notification_id, const base::Optional& button_index, - const base::Optional& reply) {} + const base::Optional& 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 ac1be55a795..1c7221570d3 100644 --- a/chromium/ui/message_center/message_center_stats_collector.cc +++ b/chromium/ui/message_center/message_center_stats_collector.cc @@ -103,7 +103,7 @@ void MessageCenterStatsCollector::OnNotificationUpdated( void MessageCenterStatsCollector::OnNotificationClicked( const std::string& notification_id, const base::Optional& button_index, - const base::Optional& reply) { + const base::Optional& 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 3770c703268..fa928a458de 100644 --- a/chromium/ui/message_center/message_center_stats_collector.h +++ b/chromium/ui/message_center/message_center_stats_collector.h @@ -73,7 +73,7 @@ class MessageCenterStatsCollector : public MessageCenterObserver { void OnNotificationClicked( const std::string& notification_id, const base::Optional& button_index, - const base::Optional& reply) override; + const base::Optional& 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 8cacf656410..5c181f1daac 100644 --- a/chromium/ui/message_center/notification_list_unittest.cc +++ b/chromium/ui/message_center/notification_list_unittest.cc @@ -6,6 +6,7 @@ #include +#include #include #include "base/i18n/time_formatting.h" @@ -32,8 +33,9 @@ class NotificationListTest : public testing::Test { ~NotificationListTest() override {} void SetUp() override { - message_center_.reset(new FakeMessageCenter()); - notification_list_.reset(new NotificationList(message_center_.get())); + message_center_ = std::make_unique(); + notification_list_ = + std::make_unique(message_center_.get()); counter_ = 0; } @@ -173,8 +175,8 @@ TEST_F(NotificationListTest, UpdateNotification) { std::string replaced = id0 + "_replaced"; EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_)); std::unique_ptr notification(new Notification( - NOTIFICATION_TYPE_SIMPLE, replaced, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), + NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), NotifierId(NotifierType::APPLICATION, kExtensionId), RichNotificationData(), nullptr)); notification_list_->UpdateNotificationMessage(id0, std::move(notification)); @@ -182,8 +184,8 @@ TEST_F(NotificationListTest, UpdateNotification) { const NotificationList::Notifications notifications = notification_list_->GetVisibleNotifications(blockers_); EXPECT_EQ(replaced, (*notifications.begin())->id()); - EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title()); - EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message()); + EXPECT_EQ(u"newtitle", (*notifications.begin())->title()); + EXPECT_EQ(u"newbody", (*notifications.begin())->message()); } TEST_F(NotificationListTest, UpdateNotificationWithRenotifyAndQuietMode) { @@ -230,34 +232,28 @@ TEST_F(NotificationListTest, GetNotificationsByNotifierId) { NotifierId id2(GURL("http://example.com")); NotifierId id3(NotifierType::SYSTEM_COMPONENT, "system-notifier"); std::unique_ptr notification(new Notification( - NOTIFICATION_TYPE_SIMPLE, "id0", UTF8ToUTF16("title0"), - UTF8ToUTF16("message0"), gfx::Image(), UTF8ToUTF16("source0"), GURL(), - id0, RichNotificationData(), nullptr)); + NOTIFICATION_TYPE_SIMPLE, "id0", u"title0", u"message0", gfx::Image(), + u"source0", GURL(), id0, RichNotificationData(), nullptr)); notification_list_->AddNotification(std::move(notification)); - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, "id1", UTF8ToUTF16("title1"), - UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source0"), GURL(), - id0, RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, "id1", u"title1", u"message1", gfx::Image(), + u"source0", GURL(), id0, RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, "id2", UTF8ToUTF16("title1"), - UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source1"), GURL(), - id0, RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, "id2", u"title1", u"message1", gfx::Image(), + u"source1", GURL(), id0, RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, "id3", UTF8ToUTF16("title1"), - UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source2"), GURL(), - id1, RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, "id3", u"title1", u"message1", gfx::Image(), + u"source2", GURL(), id1, RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, "id4", UTF8ToUTF16("title1"), - UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source2"), GURL(), - id2, RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, "id4", u"title1", u"message1", gfx::Image(), + u"source2", GURL(), id2, RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, "id5", UTF8ToUTF16("title1"), - UTF8ToUTF16("message1"), gfx::Image(), UTF8ToUTF16("source2"), GURL(), - id3, RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, "id5", u"title1", u"message1", gfx::Image(), + u"source2", GURL(), id3, RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); NotificationList::Notifications by_notifier_id = @@ -363,11 +359,10 @@ TEST_F(NotificationListTest, GetNotificationsByAppId) { // Add a notification for |app_id1|. const std::string app_id1("app_id1"); const std::string id1("id1"); - std::unique_ptr notification( - new Notification(NOTIFICATION_TYPE_PROGRESS, id1, UTF8ToUTF16("updated"), - UTF8ToUTF16("updated"), gfx::Image(), base::string16(), - GURL(), NotifierId(NotifierType::APPLICATION, app_id1), - RichNotificationData(), nullptr)); + std::unique_ptr notification(new Notification( + NOTIFICATION_TYPE_PROGRESS, id1, u"updated", u"updated", gfx::Image(), + std::u16string(), GURL(), NotifierId(NotifierType::APPLICATION, app_id1), + RichNotificationData(), nullptr)); notification_list_->AddNotification(std::move(notification)); EXPECT_EQ(1u, notification_list_->GetNotificationsByAppId(app_id1).size()); @@ -384,29 +379,26 @@ TEST_F(NotificationListTest, GetNotificationsByAppId) { EXPECT_EQ(0u, notification_list_->GetNotificationsByAppId(app_id1).size()); // Add two notifications for |app_id1| and one for |app_id2|. - notification.reset( - new Notification(NOTIFICATION_TYPE_PROGRESS, id1, UTF8ToUTF16("updated"), - UTF8ToUTF16("updated"), gfx::Image(), base::string16(), - GURL(), NotifierId(NotifierType::APPLICATION, app_id1), - RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_PROGRESS, id1, u"updated", u"updated", gfx::Image(), + std::u16string(), GURL(), NotifierId(NotifierType::APPLICATION, app_id1), + RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); const std::string id2("id2"); - notification.reset( - new Notification(NOTIFICATION_TYPE_PROGRESS, id2, UTF8ToUTF16("updated"), - UTF8ToUTF16("updated"), gfx::Image(), base::string16(), - GURL(), NotifierId(NotifierType::APPLICATION, app_id1), - RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_PROGRESS, id2, u"updated", u"updated", gfx::Image(), + std::u16string(), GURL(), NotifierId(NotifierType::APPLICATION, app_id1), + RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); EXPECT_EQ(2u, notification_list_->GetNotificationsByAppId(app_id1).size()); const std::string id3("id3"); const std::string app_id2("app_id2"); - notification.reset( - new Notification(NOTIFICATION_TYPE_PROGRESS, id3, UTF8ToUTF16("updated"), - UTF8ToUTF16("updated"), gfx::Image(), base::string16(), - GURL(), NotifierId(NotifierType::APPLICATION, app_id2), - RichNotificationData(), nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_PROGRESS, id3, u"updated", u"updated", gfx::Image(), + std::u16string(), GURL(), NotifierId(NotifierType::APPLICATION, app_id2), + RichNotificationData(), nullptr); notification_list_->AddNotification(std::move(notification)); EXPECT_EQ(2u, notification_list_->GetNotificationsByAppId(app_id1).size()); EXPECT_EQ(1u, notification_list_->GetNotificationsByAppId(app_id2).size()); @@ -474,9 +466,9 @@ TEST_F(NotificationListTest, UpdateWithoutMessageCenterView) { RichNotificationData optional; std::unique_ptr notification(new Notification( - NOTIFICATION_TYPE_SIMPLE, replaced, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - GURL(), NotifierId(NotifierType::APPLICATION, kExtensionId), optional, + NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", + gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), + NotifierId(NotifierType::APPLICATION, kExtensionId), optional, nullptr)); notification_list_->UpdateNotificationMessage(id0, std::move(notification)); EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_)); @@ -484,8 +476,8 @@ TEST_F(NotificationListTest, UpdateWithoutMessageCenterView) { const NotificationList::Notifications notifications = notification_list_->GetVisibleNotifications(blockers_); EXPECT_EQ(replaced, (*notifications.begin())->id()); - EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title()); - EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message()); + EXPECT_EQ(u"newtitle", (*notifications.begin())->title()); + EXPECT_EQ(u"newbody", (*notifications.begin())->message()); notification_list_->RemoveNotification(replaced); EXPECT_EQ(0U, @@ -505,8 +497,8 @@ TEST_F(NotificationListTest, Renotify) { RichNotificationData optional; optional.renotify = true; std::unique_ptr notification(new Notification( - NOTIFICATION_TYPE_SIMPLE, replaced, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), + NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), NotifierId(NotifierType::APPLICATION, kExtensionId), optional, nullptr)); notification_list_->UpdateNotificationMessage(id0, std::move(notification)); EXPECT_EQ(1u, notification_list_->NotificationCount(blockers_)); @@ -514,8 +506,8 @@ TEST_F(NotificationListTest, Renotify) { const NotificationList::Notifications notifications = notification_list_->GetVisibleNotifications(blockers_); EXPECT_EQ(replaced, (*notifications.begin())->id()); - EXPECT_EQ(UTF8ToUTF16("newtitle"), (*notifications.begin())->title()); - EXPECT_EQ(UTF8ToUTF16("newbody"), (*notifications.begin())->message()); + EXPECT_EQ(u"newtitle", (*notifications.begin())->title()); + EXPECT_EQ(u"newbody", (*notifications.begin())->message()); } TEST_F(NotificationListTest, PriorityAndRenotify) { @@ -529,8 +521,8 @@ TEST_F(NotificationListTest, PriorityAndRenotify) { RichNotificationData priority; priority.priority = DEFAULT_PRIORITY; std::unique_ptr notification(new Notification( - NOTIFICATION_TYPE_SIMPLE, id0, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), + NOTIFICATION_TYPE_SIMPLE, id0, u"newtitle", u"newbody", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr)); notification_list_->UpdateNotificationMessage(id0, std::move(notification)); EXPECT_EQ(1u, GetPopupCounts()); @@ -538,29 +530,28 @@ TEST_F(NotificationListTest, PriorityAndRenotify) { EXPECT_EQ(0u, GetPopupCounts()); // update with no promotion change for id0, it won't appear as a toast. - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, id0, UTF8ToUTF16("newtitle2"), - UTF8ToUTF16("newbody2"), gfx::Image(), UTF8ToUTF16(kDisplaySource), - GURL(), NotifierId(NotifierType::APPLICATION, kExtensionId), priority, - nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, id0, u"newtitle2", u"newbody2", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), + NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr); notification_list_->UpdateNotificationMessage(id0, std::move(notification)); EXPECT_EQ(0u, GetPopupCounts()); // id1 promoted to DEFAULT->HIGH, it won't reappear as a toast (popup). priority.priority = HIGH_PRIORITY; - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, id1, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), - NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, id1, u"newtitle", u"newbody", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), + NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr); notification_list_->UpdateNotificationMessage(id1, std::move(notification)); EXPECT_EQ(0u, GetPopupCounts()); // |renotify| will make it reappear as a toast (popup). priority.renotify = true; - notification.reset(new Notification( - NOTIFICATION_TYPE_SIMPLE, id1, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), - NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr)); + notification = std::make_unique( + NOTIFICATION_TYPE_SIMPLE, id1, u"newtitle", u"newbody", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), + NotifierId(NotifierType::APPLICATION, kExtensionId), priority, nullptr); notification_list_->UpdateNotificationMessage(id1, std::move(notification)); EXPECT_EQ(1u, GetPopupCounts()); notification_list_->MarkSinglePopupAsShown(id1, true); @@ -658,8 +649,8 @@ TEST_F(NotificationListTest, UpdateAfterMarkedAsShown) { const std::string replaced("test-replaced-id"); std::unique_ptr notification(new Notification( - NOTIFICATION_TYPE_SIMPLE, replaced, UTF8ToUTF16("newtitle"), - UTF8ToUTF16("newbody"), gfx::Image(), UTF8ToUTF16(kDisplaySource), GURL(), + NOTIFICATION_TYPE_SIMPLE, replaced, u"newtitle", u"newbody", gfx::Image(), + UTF8ToUTF16(kDisplaySource), GURL(), NotifierId(NotifierType::APPLICATION, kExtensionId), RichNotificationData(), nullptr)); notification_list_->UpdateNotificationMessage(id1, std::move(notification)); @@ -694,10 +685,9 @@ TEST_F(NotificationListTest, TestHasNotificationOfType) { EXPECT_FALSE(notification_list_->HasNotificationOfType( id, NOTIFICATION_TYPE_PROGRESS)); - std::unique_ptr updated_notification( - new Notification(NOTIFICATION_TYPE_PROGRESS, id, UTF8ToUTF16("updated"), - UTF8ToUTF16("updated"), gfx::Image(), base::string16(), - GURL(), NotifierId(), RichNotificationData(), nullptr)); + std::unique_ptr updated_notification(new Notification( + NOTIFICATION_TYPE_PROGRESS, id, u"updated", u"updated", gfx::Image(), + std::u16string(), GURL(), NotifierId(), RichNotificationData(), nullptr)); notification_list_->AddNotification(std::move(updated_notification)); EXPECT_FALSE( diff --git a/chromium/ui/message_center/public/cpp/message_center_constants.h b/chromium/ui/message_center/public/cpp/message_center_constants.h index c623637a0a5..d3cf0a1ae1e 100644 --- a/chromium/ui/message_center/public/cpp/message_center_constants.h +++ b/chromium/ui/message_center/public/cpp/message_center_constants.h @@ -58,17 +58,6 @@ const int kTitleLineHeight = 20; // In DIPs. const int kMessageFontSize = 12; // For everything but title. const int kMessageLineHeight = 18; // In DIPs. -// Colors. -// Background of the card. -constexpr SkColor kNotificationBackgroundColor = SK_ColorWHITE; -// The focus border. -constexpr SkColor kFocusBorderColor = SkColorSetRGB(64, 128, 250); -// Foreground of small icon image. -constexpr SkColor kSmallImageMaskForegroundColor = SK_ColorWHITE; -// Background of small icon image. -constexpr SkColor kSmallImageMaskBackgroundColor = - SkColorSetRGB(0xa3, 0xa3, 0xa3); - // For list notifications. // Not used when --enabled-new-style-notification is set. const size_t kNotificationMaximumItems = 5; @@ -89,8 +78,6 @@ const int kButtonHorizontalPadding = 16; // In DIPs. const int kButtonIconTopPadding = 11; // In DIPs. const int kButtonIconToTitlePadding = 16; // In DIPs. -constexpr SkColor kHoveredButtonBackgroundColor = SkColorSetRGB(243, 243, 243); - // Progress bar. const int kProgressBarTopPadding = 16; #if defined(OS_APPLE) diff --git a/chromium/ui/message_center/public/cpp/notification.cc b/chromium/ui/message_center/public/cpp/notification.cc index 2e390fc184a..416feb9facd 100644 --- a/chromium/ui/message_center/public/cpp/notification.cc +++ b/chromium/ui/message_center/public/cpp/notification.cc @@ -39,7 +39,7 @@ gfx::Image DuplicateImage(const gfx::Image& image) { } // namespace -ButtonInfo::ButtonInfo(const base::string16& title) : title(title) {} +ButtonInfo::ButtonInfo(const std::u16string& title) : title(title) {} ButtonInfo::ButtonInfo(const ButtonInfo& other) = default; @@ -58,10 +58,10 @@ RichNotificationData::~RichNotificationData() = default; Notification::Notification(NotificationType type, const std::string& id, - const base::string16& title, - const base::string16& message, + const std::u16string& title, + const std::u16string& message, const gfx::Image& icon, - const base::string16& display_source, + const std::u16string& display_source, const GURL& origin_url, const NotifierId& notifier_id, const RichNotificationData& optional_fields, @@ -134,18 +134,28 @@ bool Notification::UseOriginAsContextMessage() const { origin_url_.SchemeIsHTTPOrHTTPS(); } -gfx::Image Notification::GenerateMaskedSmallIcon(int dip_size, - SkColor color) const { +gfx::Image Notification::GenerateMaskedSmallIcon( + int dip_size, + SkColor mask_color, + SkColor background_color, + SkColor foreground_color) const { if (!vector_small_image().is_empty()) return gfx::Image( - gfx::CreateVectorIcon(vector_small_image(), dip_size, color)); + gfx::CreateVectorIcon(vector_small_image(), dip_size, mask_color)); if (small_image().IsEmpty()) return gfx::Image(); // If |vector_small_image| is not available, fallback to raster based // masking and resizing. - gfx::ImageSkia image = small_image().AsImageSkia(); + gfx::ImageSkia image; + if (small_image_needs_additional_masking()) { + image = GetMaskedSmallImage(small_image().AsImageSkia(), background_color, + foreground_color) + .AsImageSkia(); + } else { + image = small_image().AsImageSkia(); + } #if BUILDFLAG(IS_CHROMEOS_ASH) bool create_masked_image = @@ -156,7 +166,8 @@ gfx::Image Notification::GenerateMaskedSmallIcon(int dip_size, if (create_masked_image) { image = gfx::ImageSkiaOperations::CreateMaskedImage( - CreateSolidColorImage(image.width(), image.height(), color), image); + CreateSolidColorImage(image.width(), image.height(), mask_color), + image); } gfx::ImageSkia resized = gfx::ImageSkiaOperations::CreateResizedImage( image, skia::ImageOperations::ResizeMethod::RESIZE_BEST, @@ -164,4 +175,22 @@ gfx::Image Notification::GenerateMaskedSmallIcon(int dip_size, return gfx::Image(resized); } +// Take the alpha channel of small_image, mask it with the foreground, +// then add the masked foreground on top of the background +gfx::Image Notification::GetMaskedSmallImage(const gfx::ImageSkia& small_image, + SkColor background_color, + SkColor foreground_color) const { + int width = small_image.width(); + int height = small_image.height(); + + const gfx::ImageSkia background = + CreateSolidColorImage(width, height, background_color); + const gfx::ImageSkia foreground = + CreateSolidColorImage(width, height, foreground_color); + const gfx::ImageSkia masked_small_image = + gfx::ImageSkiaOperations::CreateMaskedImage(foreground, small_image); + return gfx::Image(gfx::ImageSkiaOperations::CreateSuperimposedImage( + background, masked_small_image)); +} + } // namespace message_center diff --git a/chromium/ui/message_center/public/cpp/notification.h b/chromium/ui/message_center/public/cpp/notification.h index 6ef34b695cc..9aa2970150d 100644 --- a/chromium/ui/message_center/public/cpp/notification.h +++ b/chromium/ui/message_center/public/cpp/notification.h @@ -12,7 +12,6 @@ #include "base/memory/ref_counted.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "base/time/time.h" #include "base/values.h" #include "build/chromeos_buildflags.h" @@ -36,8 +35,8 @@ namespace message_center { // Represents an individual item in NOTIFICATION_TYPE_MULTIPLE notifications. struct MESSAGE_CENTER_PUBLIC_EXPORT NotificationItem { - base::string16 title; - base::string16 message; + std::u16string title; + std::u16string message; }; enum class SettingsButtonHandler { @@ -51,14 +50,14 @@ enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING }; // Represents a button to be shown as part of a notification. struct MESSAGE_CENTER_PUBLIC_EXPORT ButtonInfo { - explicit ButtonInfo(const base::string16& title); + explicit ButtonInfo(const std::u16string& title); ButtonInfo(const ButtonInfo& other); ButtonInfo(); ~ButtonInfo(); ButtonInfo& operator=(const ButtonInfo& other); // Title that should be displayed on the notification button. - base::string16 title; + std::u16string title; // Icon that should be displayed on the notification button. Optional. On some // platforms, a mask will be applied to the icon, to match the visual @@ -69,7 +68,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 placeholder; + base::Optional placeholder; }; enum class FullscreenVisibility { @@ -98,7 +97,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT RichNotificationData { // Context message to display below the notification's content. Optional. May // not be used for notifications that have an explicit origin URL set. - base::string16 context_message; + std::u16string context_message; // Large image to display on the notification. Optional. gfx::Image image; @@ -107,6 +106,11 @@ class MESSAGE_CENTER_PUBLIC_EXPORT RichNotificationData { // notification. Optional. gfx::Image small_image; + // If true, the small image should be masked with the foreground and then + // added on top of the background. Masking is delayed until the notification + // is in the views hierarchy or about to be passed to the OS. + bool small_image_needs_additional_masking = false; + #if BUILDFLAG(IS_CHROMEOS_ASH) // If true, we simply use the raw |small_image| icon, ignoring accent color // styling. For example, this is used with raw icons received from Android. @@ -138,7 +142,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT RichNotificationData { // Status text string shown in NOTIFICATION_TYPE_PROGRESS notifications. // If MD style notification is not enabled, this attribute is ignored. - base::string16 progress_status; + std::u16string progress_status; // Buttons that should show up on the notification. A maximum of 16 buttons // is supported by the current implementation, but this may differ between @@ -169,7 +173,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT RichNotificationData { bool silent = false; // An accessible description of the notification's contents. - base::string16 accessible_name; + std::u16string accessible_name; // Unified theme color used in new style notification. // Usually, it should not be set directly. @@ -210,10 +214,10 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { // and receives events on its behalf. May be omitted. Notification(NotificationType type, const std::string& id, - const base::string16& title, - const base::string16& message, + const std::u16string& title, + const std::u16string& message, const gfx::Image& icon, - const base::string16& display_source, + const std::u16string& display_source, const GURL& origin_url, const NotifierId& notifier_id, const RichNotificationData& optional_fields, @@ -256,11 +260,11 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { // NotificationUIManager interface. const std::string& id() const { return id_; } - const base::string16& title() const { return title_; } - void set_title(const base::string16& title) { title_ = title; } + const std::u16string& title() const { return title_; } + void set_title(const std::u16string& title) { title_ = title; } - const base::string16& message() const { return message_; } - void set_message(const base::string16& message) { message_ = message; } + const std::u16string& message() const { return message_; } + void set_message(const std::u16string& message) { message_ = message; } // The origin URL of the script which requested the notification. // Can be empty if the notification is requested by an extension or @@ -269,7 +273,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { void set_origin_url(const GURL& origin_url) { origin_url_ = origin_url; } // A display string for the source of the notification. - const base::string16& display_source() const { return display_source_; } + const std::u16string& display_source() const { return display_source_; } const NotifierId& notifier_id() const { return notifier_id_; } @@ -306,11 +310,11 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { optional_fields_.timestamp = timestamp; } - const base::string16 context_message() const { + const std::u16string context_message() const { return optional_fields_.context_message; } - void set_context_message(const base::string16& context_message) { + void set_context_message(const std::u16string& context_message) { optional_fields_.context_message = context_message; } @@ -327,10 +331,10 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { int progress() const { return optional_fields_.progress; } void set_progress(int progress) { optional_fields_.progress = progress; } - base::string16 progress_status() const { + std::u16string progress_status() const { return optional_fields_.progress_status; } - void set_progress_status(const base::string16& progress_status) { + void set_progress_status(const std::u16string& progress_status) { optional_fields_.progress_status = progress_status; } @@ -348,6 +352,14 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { optional_fields_.small_image = image; } + bool small_image_needs_additional_masking() const { + return optional_fields_.small_image_needs_additional_masking; + } + void set_small_image_needs_additional_masking(bool needs_additional_masking) { + optional_fields_.small_image_needs_additional_masking = + needs_additional_masking; + } + const gfx::VectorIcon& vector_small_image() const { return *optional_fields_.vector_small_image; } @@ -363,7 +375,14 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { // filled by the |color|. // Otherwise, it uses alpha channel of the rasterized |small_image| for // masking. - gfx::Image GenerateMaskedSmallIcon(int dip_size, SkColor color) const; + gfx::Image GenerateMaskedSmallIcon(int dip_size, + SkColor mask_color, + SkColor background_color, + SkColor foreground_color) const; + + gfx::Image GetMaskedSmallImage(const gfx::ImageSkia& small_image, + SkColor background_color, + SkColor foreground_color) const; // Buttons, with icons fetched asynchronously. const std::vector& buttons() const { @@ -396,7 +415,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { #endif // BUILDFLAG(IS_CHROMEOS_ASH) // Gets a text for spoken feedback. - const base::string16& accessible_name() const { + const std::u16string& accessible_name() const { return optional_fields_.accessible_name; } @@ -464,8 +483,8 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { NotificationType type_; std::string id_; - base::string16 title_; - base::string16 message_; + std::u16string title_; + std::u16string message_; // Image data for the associated icon, used by Ash when available. gfx::Image icon_; @@ -473,7 +492,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { // The display string for the source of the notification. Could be // the same as |origin_url_|, or the name of an extension. // Expected to be a localized user facing string. - base::string16 display_source_; + std::u16string display_source_; private: // The origin URL of the script which requested the notification. diff --git a/chromium/ui/message_center/public/cpp/notification_delegate.cc b/chromium/ui/message_center/public/cpp/notification_delegate.cc index c0a1b63b58e..4710f6f3a39 100644 --- a/chromium/ui/message_center/public/cpp/notification_delegate.cc +++ b/chromium/ui/message_center/public/cpp/notification_delegate.cc @@ -22,7 +22,7 @@ void ThunkNotificationDelegate::Close(bool by_user) { void ThunkNotificationDelegate::Click( const base::Optional& button_index, - const base::Optional& reply) { + const base::Optional& reply) { if (impl_) impl_->Click(button_index, reply); } @@ -74,7 +74,7 @@ HandleNotificationClickDelegate::~HandleNotificationClickDelegate() {} void HandleNotificationClickDelegate::Click( const base::Optional& button_index, - const base::Optional& reply) { + const base::Optional& 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 7f3c00449f6..028864bb16a 100644 --- a/chromium/ui/message_center/public/cpp/notification_delegate.h +++ b/chromium/ui/message_center/public/cpp/notification_delegate.h @@ -13,7 +13,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "ui/message_center/public/cpp/message_center_public_export.h" namespace message_center { @@ -30,7 +29,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT NotificationObserver { // |reply| is filled in if there was an input field associated with the // button. virtual void Click(const base::Optional& button_index, - const base::Optional& reply) {} + const base::Optional& reply) {} // Called when the user clicks the settings button in a notification which has // a DELEGATE settings button action. @@ -64,7 +63,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT ThunkNotificationDelegate // NotificationDelegate: void Close(bool by_user) override; void Click(const base::Optional& button_index, - const base::Optional& reply) override; + const base::Optional& reply) override; void SettingsClick() override; void DisableNotification() override; @@ -105,7 +104,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT HandleNotificationClickDelegate // NotificationDelegate overrides: void Click(const base::Optional& button_index, - const base::Optional& reply) override; + const base::Optional& reply) override; protected: ~HandleNotificationClickDelegate() override; diff --git a/chromium/ui/message_center/public/cpp/notifier_id.h b/chromium/ui/message_center/public/cpp/notifier_id.h index 97415490393..5638892d120 100644 --- a/chromium/ui/message_center/public/cpp/notifier_id.h +++ b/chromium/ui/message_center/public/cpp/notifier_id.h @@ -11,7 +11,6 @@ #include #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/gfx/image/image.h" #include "ui/message_center/public/cpp/message_center_public_export.h" #include "url/gurl.h" 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 98cd33d5b22..585902e4895 100644 --- a/chromium/ui/message_center/views/message_popup_collection_unittest.cc +++ b/chromium/ui/message_center/views/message_popup_collection_unittest.cc @@ -240,9 +240,9 @@ class MessagePopupCollectionTest : public views::ViewsTestBase, const std::string& title) { return std::make_unique( NOTIFICATION_TYPE_BASE_FORMAT, id, base::UTF8ToUTF16(title), - base::UTF8ToUTF16("test message"), gfx::Image(), - base::string16() /* display_source */, GURL(), NotifierId(), - RichNotificationData(), new NotificationDelegate()); + u"test message", gfx::Image(), std::u16string() /* display_source */, + GURL(), NotifierId(), RichNotificationData(), + new NotificationDelegate()); } std::string AddNotification() { @@ -431,7 +431,7 @@ TEST_F(MessagePopupCollectionTest, UpdateContents) { EXPECT_FALSE(GetPopup(id)->updated()); auto updated_notification = CreateNotification(id); - updated_notification->set_message(base::ASCIIToUTF16("updated")); + updated_notification->set_message(u"updated"); MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification)); EXPECT_EQ(1u, GetPopupCounts()); EXPECT_TRUE(GetPopup(id)->updated()); @@ -448,7 +448,7 @@ TEST_F(MessagePopupCollectionTest, UpdateContentsCausesPopupClose) { GetPopup(id)->set_height_after_update(2048); auto updated_notification = CreateNotification(id); - updated_notification->set_message(base::ASCIIToUTF16("updated")); + updated_notification->set_message(u"updated"); MessageCenter::Get()->UpdateNotification(id, std::move(updated_notification)); RunPendingMessages(); EXPECT_EQ(0u, GetPopupCounts()); diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc index 5e3b914c55e..fc0c0d72c9d 100644 --- a/chromium/ui/message_center/views/message_view.cc +++ b/chromium/ui/message_center/views/message_view.cc @@ -40,14 +40,14 @@ namespace { // Creates a text for spoken feedback from the data contained in the // notification. -base::string16 CreateAccessibleName(const Notification& notification) { +std::u16string CreateAccessibleName(const Notification& notification) { if (!notification.accessible_name().empty()) return notification.accessible_name(); // Fall back to a text constructed from the notification. // Add non-empty elements. - std::vector accessible_lines; + std::vector accessible_lines; if (!notification.title().empty()) accessible_lines.push_back(notification.title()); @@ -58,10 +58,9 @@ base::string16 CreateAccessibleName(const Notification& notification) { accessible_lines.push_back(notification.context_message()); std::vector items = notification.items(); for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) { - accessible_lines.push_back(items[i].title + base::ASCIIToUTF16(" ") + - items[i].message); + accessible_lines.push_back(items[i].title + u" " + items[i].message); } - return base::JoinString(accessible_lines, base::ASCIIToUTF16("\n")); + return base::JoinString(accessible_lines, u"\n"); } bool ShouldShowAeroShadowBorder() { @@ -116,7 +115,7 @@ MessageView::~MessageView() { void MessageView::UpdateWithNotification(const Notification& notification) { pinned_ = notification.pinned(); - base::string16 new_accessible_name = CreateAccessibleName(notification); + std::u16string new_accessible_name = CreateAccessibleName(notification); if (new_accessible_name != accessible_name_) { accessible_name_ = new_accessible_name; NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); @@ -473,8 +472,11 @@ bool MessageView::ShouldShowControlButtons() const { } void MessageView::UpdateBackgroundPainter() { - SkColor background_color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_NotificationDefaultBackground); + auto* theme = GetNativeTheme(); + SkColor background_color = theme->GetSystemColor( + is_active_ ? ui::NativeTheme::kColorId_NotificationBackgroundActive + : ui::NativeTheme::kColorId_NotificationBackground); + SetBackground(views::CreateBackgroundFromPainter( std::make_unique( top_radius_, bottom_radius_, background_color))); @@ -487,9 +489,8 @@ void MessageView::UpdateControlButtonsVisibility() { } void MessageView::SetDrawBackgroundAsActive(bool active) { - background()->SetNativeControlColor(active ? kHoveredButtonBackgroundColor - : kNotificationBackgroundColor); - SchedulePaint(); + is_active_ = active; + UpdateBackgroundPainter(); } } // namespace message_center diff --git a/chromium/ui/message_center/views/message_view.h b/chromium/ui/message_center/views/message_view.h index f8c2e3bc1b0..c8df0cfa62c 100644 --- a/chromium/ui/message_center/views/message_view.h +++ b/chromium/ui/message_center/views/message_view.h @@ -6,11 +6,11 @@ #define UI_MESSAGE_CENTER_VIEWS_MESSAGE_VIEW_H_ #include +#include #include "base/macros.h" #include "base/observer_list.h" #include "base/observer_list_types.h" -#include "base/strings/string16.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/insets.h" @@ -211,7 +211,11 @@ class MESSAGE_CENTER_EXPORT MessageView std::string notification_id_; views::ScrollView* scroller_ = nullptr; - base::string16 accessible_name_; + std::u16string accessible_name_; + + // Tracks whether background should be drawn as active based on gesture + // events. + bool is_active_ = false; // Flag if the notification is set to pinned or not. See the comment in // MessageView::Mode for detail. diff --git a/chromium/ui/message_center/views/notification_control_buttons_unittest.cc b/chromium/ui/message_center/views/notification_control_buttons_unittest.cc index b5354da7bf5..376a8464243 100644 --- a/chromium/ui/message_center/views/notification_control_buttons_unittest.cc +++ b/chromium/ui/message_center/views/notification_control_buttons_unittest.cc @@ -44,8 +44,8 @@ class NotificationControlButtonsTest : public testing::Test { void SetUp() override { Test::SetUp(); Notification notification( - NOTIFICATION_TYPE_SIMPLE, "id", base::UTF8ToUTF16("title"), - base::UTF8ToUTF16("id"), gfx::Image(), base::string16(), GURL(), + NOTIFICATION_TYPE_SIMPLE, "id", u"title", u"id", gfx::Image(), + std::u16string(), GURL(), NotifierId(NotifierType::APPLICATION, "notifier_id"), RichNotificationData(), nullptr); message_view_ = std::make_unique(notification); diff --git a/chromium/ui/message_center/views/notification_header_view.cc b/chromium/ui/message_center/views/notification_header_view.cc index 9d30a8ac410..927e50f51bd 100644 --- a/chromium/ui/message_center/views/notification_header_view.cc +++ b/chromium/ui/message_center/views/notification_header_view.cc @@ -65,7 +65,7 @@ constexpr int kExpandIconSize = 8; constexpr gfx::Insets kExpandIconViewPadding(13, 2, 9, 0); // Bullet character. The divider symbol between different parts of the header. -constexpr wchar_t kNotificationHeaderDivider[] = L" \u2022 "; +constexpr char16_t kNotificationHeaderDivider[] = u" \u2022 "; // "Roboto-Regular, 12sp" is specified in the mock. constexpr int kHeaderTextFontSize = 12; @@ -220,7 +220,7 @@ NotificationHeaderView::NotificationHeaderView(PressedCallback callback) // Summary text divider summary_text_divider_ = create_label(); - summary_text_divider_->SetText(base::WideToUTF16(kNotificationHeaderDivider)); + summary_text_divider_->SetText(kNotificationHeaderDivider); summary_text_divider_->SetVisible(false); detail_views_->AddChildView(summary_text_divider_); @@ -232,7 +232,7 @@ NotificationHeaderView::NotificationHeaderView(PressedCallback callback) // Timestamp divider timestamp_divider_ = create_label(); - timestamp_divider_->SetText(base::WideToUTF16(kNotificationHeaderDivider)); + timestamp_divider_->SetText(kNotificationHeaderDivider); timestamp_divider_->SetVisible(false); detail_views_->AddChildView(timestamp_divider_); @@ -275,7 +275,7 @@ void NotificationHeaderView::ClearAppIcon() { UpdateColors(); } -void NotificationHeaderView::SetAppName(const base::string16& name) { +void NotificationHeaderView::SetAppName(const std::u16string& name) { app_name_view_->SetText(name); } @@ -291,7 +291,7 @@ void NotificationHeaderView::SetProgress(int progress) { UpdateSummaryTextVisibility(); } -void NotificationHeaderView::SetSummaryText(const base::string16& text) { +void NotificationHeaderView::SetSummaryText(const std::u16string& text) { summary_text_view_->SetText(text); has_progress_ = false; UpdateSummaryTextVisibility(); @@ -309,8 +309,7 @@ void NotificationHeaderView::GetAccessibleNodeData(ui::AXNodeData* node_data) { node_data->role = ax::mojom::Role::kGenericContainer; node_data->SetName(app_name_view_->GetText()); - node_data->SetDescription(summary_text_view_->GetText() + - base::ASCIIToUTF16(" ") + + node_data->SetDescription(summary_text_view_->GetText() + u" " + timestamp_view_->GetText()); if (is_expanded_) @@ -323,7 +322,7 @@ void NotificationHeaderView::OnThemeChanged() { } void NotificationHeaderView::SetTimestamp(base::Time timestamp) { - base::string16 relative_time; + std::u16string relative_time; base::TimeDelta next_update; GetRelativeTimeStringAndNextUpdateTime(timestamp - base::Time::Now(), &relative_time, &next_update); @@ -389,7 +388,7 @@ void NotificationHeaderView::SetAppIconVisible(bool visible) { app_icon_view_->SetVisible(visible); } -const base::string16& NotificationHeaderView::app_name_for_testing() const { +const std::u16string& NotificationHeaderView::app_name_for_testing() const { return app_name_view_->GetText(); } diff --git a/chromium/ui/message_center/views/notification_header_view.h b/chromium/ui/message_center/views/notification_header_view.h index 6b59bc884ad..0c5d59dd510 100644 --- a/chromium/ui/message_center/views/notification_header_view.h +++ b/chromium/ui/message_center/views/notification_header_view.h @@ -30,7 +30,7 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button { ~NotificationHeaderView() override; void SetAppIcon(const gfx::ImageSkia& img); - void SetAppName(const base::string16& name); + void SetAppName(const std::u16string& name); void SetAppNameElideBehavior(gfx::ElideBehavior elide_behavior); // Only show AppIcon and AppName in settings mode. @@ -39,7 +39,7 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button { // Progress, summary and overflow indicator are all the same UI element so are // mutually exclusive. void SetProgress(int progress); - void SetSummaryText(const base::string16& text); + void SetSummaryText(const std::u16string& text); void SetOverflowIndicator(int count); void SetTimestamp(base::Time timestamp); @@ -81,7 +81,7 @@ class MESSAGE_CENTER_EXPORT NotificationHeaderView : public views::Button { return timestamp_view_; } - const base::string16& app_name_for_testing() const; + const std::u16string& app_name_for_testing() const; const gfx::ImageSkia& app_icon_for_testing() const; diff --git a/chromium/ui/message_center/views/notification_header_view_unittest.cc b/chromium/ui/message_center/views/notification_header_view_unittest.cc index e7ccc97ccdb..a8468fc8000 100644 --- a/chromium/ui/message_center/views/notification_header_view_unittest.cc +++ b/chromium/ui/message_center/views/notification_header_view_unittest.cc @@ -134,7 +134,7 @@ TEST_F(NotificationHeaderViewTest, AllowsHidingOfAppIcon) { TEST_F(NotificationHeaderViewTest, SetProgress) { int progress = 50; - base::string16 expected_summary_text = l10n_util::GetStringFUTF16Int( + std::u16string expected_summary_text = l10n_util::GetStringFUTF16Int( IDS_MESSAGE_CENTER_NOTIFICATION_PROGRESS_PERCENTAGE, progress); notification_header_view_->SetProgress(progress); @@ -146,7 +146,7 @@ TEST_F(NotificationHeaderViewTest, SetProgress) { TEST_F(NotificationHeaderViewTest, SetOverflowIndicator) { int count = 10; - base::string16 expected_summary_text = l10n_util::GetStringFUTF16Int( + std::u16string expected_summary_text = l10n_util::GetStringFUTF16Int( IDS_MESSAGE_CENTER_LIST_NOTIFICATION_HEADER_OVERFLOW_INDICATOR, count); notification_header_view_->SetOverflowIndicator(count); @@ -157,7 +157,7 @@ TEST_F(NotificationHeaderViewTest, SetOverflowIndicator) { } TEST_F(NotificationHeaderViewTest, SetSummaryText) { - base::string16 expected_summary_text = base::ASCIIToUTF16("summary"); + std::u16string expected_summary_text = u"summary"; notification_header_view_->SetSummaryText(expected_summary_text); @@ -180,12 +180,12 @@ TEST_F(NotificationHeaderViewTest, TimestampHiddenWithProgress) { EXPECT_TRUE(timestamp_view->GetVisible()); // Make sure we show the timestamp view with summary text. - notification_header_view_->SetSummaryText(base::ASCIIToUTF16("summary")); + notification_header_view_->SetSummaryText(u"summary"); EXPECT_TRUE(timestamp_view->GetVisible()); } TEST_F(NotificationHeaderViewTest, ColorContrastEnforcement) { - notification_header_view_->SetSummaryText(base::ASCIIToUTF16("summary")); + notification_header_view_->SetSummaryText(u"summary"); auto* summary_text = notification_header_view_->summary_text_for_testing(); notification_header_view_->ClearAppIcon(); notification_header_view_->SetExpandButtonEnabled(true); diff --git a/chromium/ui/message_center/views/notification_view_md.cc b/chromium/ui/message_center/views/notification_view_md.cc index feb4a125add..c0b9429df2b 100644 --- a/chromium/ui/message_center/views/notification_view_md.cc +++ b/chromium/ui/message_center/views/notification_view_md.cc @@ -194,11 +194,11 @@ const char* CompactTitleMessageView::GetClassName() const { CompactTitleMessageView::CompactTitleMessageView() { title_ = AddChildView(std::make_unique( - base::string16(), views::style::CONTEXT_DIALOG_BODY_TEXT)); + std::u16string(), views::style::CONTEXT_DIALOG_BODY_TEXT)); title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); message_ = AddChildView(std::make_unique( - base::string16(), views::style::CONTEXT_DIALOG_BODY_TEXT, + std::u16string(), views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY)); message_->SetHorizontalAlignment(gfx::ALIGN_RIGHT); } @@ -232,11 +232,11 @@ void CompactTitleMessageView::Layout() { message_->SetBounds(width() - message_width, 0, message_width, height()); } -void CompactTitleMessageView::set_title(const base::string16& title) { +void CompactTitleMessageView::set_title(const std::u16string& title) { title_->SetText(title); } -void CompactTitleMessageView::set_message(const base::string16& message) { +void CompactTitleMessageView::set_message(const std::u16string& message) { message_->SetText(message); } @@ -306,8 +306,8 @@ gfx::Size LargeImageView::GetResizedImageSize() { NotificationMdTextButton::NotificationMdTextButton( PressedCallback callback, - const base::string16& label, - const base::Optional& placeholder) + const std::u16string& label, + const base::Optional& placeholder) : views::MdTextButton(std::move(callback), label), placeholder_(placeholder) { SetMinSize(kActionButtonMinSize); @@ -356,7 +356,7 @@ NotificationInputContainerMD::NotificationInputContainerMD( auto* layout = SetLayoutManager(std::make_unique( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0)); - SetInkDropMode(InkDropMode::ON); + SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); SetInkDropVisibleOpacity(1); AddChildView(ink_drop_container_); @@ -419,10 +419,11 @@ void NotificationInputContainerMD::OnThemeChanged() { auto* theme = GetNativeTheme(); SetBackground(views::CreateSolidBackground(theme->GetSystemColor( ui::NativeTheme::kColorId_NotificationActionsRowBackground))); - textfield_->SetTextColor(SK_ColorWHITE); + textfield_->SetTextColor( + theme->GetSystemColor(ui::NativeTheme::kColorId_NotificationColor)); textfield_->SetBackgroundColor(SK_ColorTRANSPARENT); textfield_->set_placeholder_text_color(theme->GetSystemColor( - ui::NativeTheme::kColorId_NotificationEmptyPlaceholderTextColor)); + ui::NativeTheme::kColorId_NotificationPlaceholderColor)); SetButtonImage(); } @@ -438,7 +439,7 @@ bool NotificationInputContainerMD::HandleKeyEvent(views::Textfield* sender, event.key_code() == ui::VKEY_RETURN) { delegate_->OnNotificationInputSubmit( textfield_->GetProperty(kTextfieldIndexKey), textfield_->GetText()); - textfield_->SetText(base::string16()); + textfield_->SetText(std::u16string()); return true; } return event.type() == ui::ET_KEY_RELEASED; @@ -450,22 +451,21 @@ void NotificationInputContainerMD::OnAfterUserAction(views::Textfield* sender) { } void NotificationInputContainerMD::SetButtonImage() { - auto placeholder_icon_color_id = + auto icon_color_id = textfield_->GetText().empty() - ? ui::NativeTheme::kColorId_NotificationEmptyPlaceholderIconColor - : ui::NativeTheme::kColorId_NotificationPlaceholderIconColor; + ? ui::NativeTheme::kColorId_NotificationPlaceholderColor + : ui::NativeTheme::kColorId_NotificationColor; button_->SetImage( views::Button::STATE_NORMAL, - gfx::CreateVectorIcon( - kNotificationInlineReplyIcon, kInputReplyButtonSize, - GetNativeTheme()->GetSystemColor(placeholder_icon_color_id))); + gfx::CreateVectorIcon(kNotificationInlineReplyIcon, kInputReplyButtonSize, + GetNativeTheme()->GetSystemColor(icon_color_id))); } // InlineSettingsRadioButton /////////////////////////////////////////////////// class InlineSettingsRadioButton : public views::RadioButton { public: - explicit InlineSettingsRadioButton(const base::string16& label_text) + explicit InlineSettingsRadioButton(const std::u16string& label_text) : views::RadioButton(label_text, 1 /* group */) { label()->SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT); label()->SetSubpixelRenderingEnabled(false); @@ -476,7 +476,7 @@ class InlineSettingsRadioButton : public views::RadioButton { SetEnabledTextColors(GetTextColor()); label()->SetAutoColorReadabilityEnabled(true); label()->SetBackgroundColor(GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_NotificationInlineSettingsBackground)); + ui::NativeTheme::kColorId_NotificationBackgroundActive)); } private: @@ -795,7 +795,7 @@ void NotificationViewMD::UpdateControlButtonsVisibilityWithNotification( } void NotificationViewMD::OnNotificationInputSubmit(size_t index, - const base::string16& text) { + const std::u16string& text) { MessageCenter::Get()->ClickOnNotificationButtonWithReply(notification_id(), index, text); } @@ -805,9 +805,9 @@ void NotificationViewMD::CreateOrUpdateContextTitleView( header_row_->SetAccentColor(notification.accent_color()); header_row_->SetTimestamp(notification.timestamp()); header_row_->SetAppNameElideBehavior(gfx::ELIDE_TAIL); - header_row_->SetSummaryText(base::string16()); + header_row_->SetSummaryText(std::u16string()); - base::string16 app_name; + std::u16string app_name; if (notification.UseOriginAsContextMessage()) { app_name = url_formatter::FormatUrlForSecurityDisplay( notification.origin_url(), @@ -838,7 +838,7 @@ void NotificationViewMD::CreateOrUpdateTitleView( int title_character_limit = kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacterMD; - base::string16 title = gfx::TruncateString( + std::u16string title = gfx::TruncateString( notification.title(), title_character_limit, gfx::WORD_BREAK); if (!title_view_) { title_view_ = @@ -868,7 +868,7 @@ void NotificationViewMD::CreateOrUpdateMessageView( return; } - base::string16 text = gfx::TruncateString( + std::u16string text = gfx::TruncateString( notification.message(), kMessageCharacterLimitMD, gfx::WORD_BREAK); if (!message_view_) { @@ -952,7 +952,7 @@ void NotificationViewMD::CreateOrUpdateProgressStatusView( if (!status_view_) { status_view_ = left_content_->AddChildViewAt( - std::make_unique(base::string16(), + std::make_unique(std::u16string(), views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY), left_content_count_); @@ -1022,10 +1022,15 @@ void NotificationViewMD::CreateOrUpdateSmallIconView( accent_color, GetNotificationHeaderViewBackgroundColor()) .color; + auto* theme = GetNativeTheme(); // TODO(knollr): figure out if this has a performance impact and // cache images if so. (crbug.com/768748) - gfx::Image masked_small_icon = - notification.GenerateMaskedSmallIcon(kSmallImageSizeMD, icon_color); + gfx::Image masked_small_icon = notification.GenerateMaskedSmallIcon( + kSmallImageSizeMD, icon_color, + theme->GetSystemColor( + ui::NativeTheme::kColorId_MessageCenterSmallImageMaskBackground), + theme->GetSystemColor( + ui::NativeTheme::kColorId_MessageCenterSmallImageMaskForeground)); if (masked_small_icon.IsEmpty()) { header_row_->ClearAppIcon(); @@ -1090,7 +1095,7 @@ void NotificationViewMD::CreateOrUpdateActionButtonViews( for (size_t i = 0; i < buttons.size(); ++i) { ButtonInfo button_info = buttons[i]; - base::string16 label = base::i18n::ToUpper(button_info.title); + std::u16string label = base::i18n::ToUpper(button_info.title); if (new_buttons) { action_buttons_.push_back(action_buttons_row_->AddChildView( std::make_unique( @@ -1215,7 +1220,7 @@ void NotificationViewMD::HeaderRowPressed() { void NotificationViewMD::ActionButtonPressed(size_t index, const ui::Event& event) { - const base::Optional& placeholder = + const base::Optional& placeholder = action_buttons_[index]->placeholder(); if (placeholder) { inline_reply_->textfield()->SetProperty(kTextfieldIndexKey, int{index}); @@ -1296,7 +1301,7 @@ void NotificationViewMD::UpdateViewForExpandedState(bool expanded) { if (list_items_count_ > max_items) header_row_->SetOverflowIndicator(list_items_count_ - max_items); else if (!item_views_.empty()) - header_row_->SetSummaryText(base::string16()); + header_row_->SetSummaryText(std::u16string()); bool has_icon = icon_view_ && (!hide_icon_on_expanded_ || !expanded); right_content_->SetVisible(has_icon); @@ -1379,8 +1384,8 @@ SkColor NotificationViewMD::GetNotificationHeaderViewBackgroundColor() const { bool inline_settings_visible = settings_row_ && settings_row_->GetVisible(); return GetNativeTheme()->GetSystemColor( inline_settings_visible - ? ui::NativeTheme::kColorId_NotificationInlineSettingsBackground - : ui::NativeTheme::kColorId_NotificationDefaultBackground); + ? ui::NativeTheme::kColorId_NotificationBackgroundActive + : ui::NativeTheme::kColorId_NotificationBackground); } void NotificationViewMD::UpdateActionButtonsRowBackground() { @@ -1477,7 +1482,7 @@ std::vector NotificationViewMD::GetChildrenForLayerAdjustment() SkColor NotificationViewMD::GetInkDropBaseColor() const { return GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_NotificationInlineSettingsBackground); + ui::NativeTheme::kColorId_NotificationBackgroundActive); } void NotificationViewMD::InkDropAnimationStarted() { diff --git a/chromium/ui/message_center/views/notification_view_md.h b/chromium/ui/message_center/views/notification_view_md.h index 528b642bc36..946f34a1cd2 100644 --- a/chromium/ui/message_center/views/notification_view_md.h +++ b/chromium/ui/message_center/views/notification_view_md.h @@ -41,18 +41,18 @@ class MESSAGE_CENTER_EXPORT NotificationMdTextButton METADATA_HEADER(NotificationMdTextButton); NotificationMdTextButton(PressedCallback callback, - const base::string16& label, - const base::Optional& placeholder); + const std::u16string& label, + const base::Optional& placeholder); ~NotificationMdTextButton() override; // views::MdTextButton: void UpdateBackgroundColor() override; void OnThemeChanged() override; - const base::Optional& placeholder() const { + const base::Optional& placeholder() const { return placeholder_; } - void set_placeholder(base::Optional placeholder) { + void set_placeholder(base::Optional placeholder) { placeholder_ = std::move(placeholder); } SkColor enabled_color_for_testing() const { @@ -62,7 +62,7 @@ class MESSAGE_CENTER_EXPORT NotificationMdTextButton void OverrideTextColor(base::Optional text_color); private: - base::Optional placeholder_; + base::Optional placeholder_; base::Optional text_color_; }; @@ -78,8 +78,8 @@ class CompactTitleMessageView : public views::View { gfx::Size CalculatePreferredSize() const override; void Layout() override; - void set_title(const base::string16& title); - void set_message(const base::string16& message); + void set_title(const std::u16string& title); + void set_message(const std::u16string& message); private: views::Label* title_ = nullptr; @@ -112,7 +112,7 @@ class LargeImageView : public views::View { class NotificationInputDelegate { public: virtual void OnNotificationInputSubmit(size_t index, - const base::string16& text) = 0; + const std::u16string& text) = 0; virtual ~NotificationInputDelegate() = default; }; @@ -211,7 +211,7 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD // Overridden from NotificationInputDelegate: void OnNotificationInputSubmit(size_t index, - const base::string16& text) override; + const std::u16string& text) override; protected: views::View* image_container_view() { return image_container_view_; } 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 25d5ecf6bc1..bef957c5f43 100644 --- a/chromium/ui/message_center/views/notification_view_md_unittest.cc +++ b/chromium/ui/message_center/views/notification_view_md_unittest.cc @@ -26,6 +26,7 @@ #include "ui/message_center/views/notification_header_view.h" #include "ui/message_center/views/padded_button.h" #include "ui/message_center/views/proportional_image_view.h" +#include "ui/native_theme/native_theme.h" #include "ui/views/animation/ink_drop_impl.h" #include "ui/views/animation/ink_drop_observer.h" #include "ui/views/animation/test/ink_drop_impl_test_api.h" @@ -52,7 +53,7 @@ class NotificationTestDelegate : public NotificationDelegate { NotificationTestDelegate() = default; void Click(const base::Optional& button_index, - const base::Optional& reply) override { + const base::Optional& 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_) @@ -64,7 +65,7 @@ class NotificationTestDelegate : public NotificationDelegate { clicked_ = true; clicked_button_index_ = button_index.value_or(false); - submitted_reply_string_ = reply.value_or(base::string16()); + submitted_reply_string_ = reply.value_or(std::u16string()); } void Reset() { @@ -77,7 +78,7 @@ class NotificationTestDelegate : public NotificationDelegate { bool clicked() const { return clicked_; } int clicked_button_index() const { return clicked_button_index_; } - const base::string16& submitted_reply_string() const { + const std::u16string& submitted_reply_string() const { return submitted_reply_string_; } bool disable_notification_called() { return disable_notification_called_; } @@ -94,7 +95,7 @@ class NotificationTestDelegate : public NotificationDelegate { bool clicked_ = false; int clicked_button_index_ = -1; - base::string16 submitted_reply_string_; + std::u16string submitted_reply_string_; bool expecting_click_ = false; bool expecting_button_click_ = false; bool expecting_reply_submission_ = false; @@ -196,8 +197,7 @@ std::unique_ptr NotificationViewMDTest::CreateSimpleNotification() std::unique_ptr notification = std::make_unique( NOTIFICATION_TYPE_BASE_FORMAT, std::string(kDefaultNotificationId), - base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message"), - CreateTestImage(80, 80), base::UTF8ToUTF16("display source"), GURL(), + u"title", u"message", CreateTestImage(80, 80), u"display source", GURL(), NotifierId(NotifierType::APPLICATION, "extension_id"), data, delegate_); notification->set_small_image(CreateTestImage(16, 16)); notification->set_image(CreateTestImage(320, 240)); @@ -270,7 +270,7 @@ const SkBitmap NotificationViewMDTest::CreateBitmap(int width, } std::vector NotificationViewMDTest::CreateButtons(int number) { - ButtonInfo info(base::ASCIIToUTF16("Test button.")); + ButtonInfo info(u"Test button."); return std::vector(number, info); } @@ -401,8 +401,8 @@ TEST_F(NotificationViewMDTest, CreateOrUpdateTest) { std::unique_ptr notification = CreateSimpleNotification(); notification->set_image(gfx::Image()); - notification->set_title(base::string16()); - notification->set_message(base::string16()); + notification->set_title(std::u16string()); + notification->set_message(std::u16string()); notification->set_icon(gfx::Image()); notification_view()->CreateOrUpdateViews(*notification); @@ -422,7 +422,7 @@ TEST_F(NotificationViewMDTest, UpdateViewsOrderingTest) { notification_view()->message_view_)); std::unique_ptr notification = CreateSimpleNotification(); - notification->set_title(base::string16()); + notification->set_title(std::u16string()); notification_view()->CreateOrUpdateViews(*notification); @@ -431,7 +431,7 @@ TEST_F(NotificationViewMDTest, UpdateViewsOrderingTest) { EXPECT_EQ(0, notification_view()->left_content_->GetIndexOf( notification_view()->message_view_)); - notification->set_title(base::UTF8ToUTF16("title")); + notification->set_title(u"title"); notification_view()->CreateOrUpdateViews(*notification); @@ -614,7 +614,7 @@ TEST_F(NotificationViewMDTest, TestInlineReply) { delegate_->set_expecting_reply_submission(true); std::vector buttons = CreateButtons(2); - buttons[1].placeholder = base::string16(); + buttons[1].placeholder = std::u16string(); notification->set_buttons(buttons); UpdateNotificationViews(*notification); notification_view()->GetWidget()->Show(); @@ -662,7 +662,7 @@ TEST_F(NotificationViewMDTest, TestInlineReply) { generator.PressKey(ui::VKEY_RETURN, ui::EF_NONE); generator.ReleaseKey(ui::VKEY_RETURN, ui::EF_NONE); EXPECT_EQ(1, delegate_->clicked_button_index()); - EXPECT_EQ(base::ASCIIToUTF16("test"), delegate_->submitted_reply_string()); + EXPECT_EQ(u"test", delegate_->submitted_reply_string()); // Reset values. delegate_->Reset(); @@ -677,7 +677,7 @@ TEST_F(NotificationViewMDTest, TestInlineReply) { // Nothing should be submitted at this point. EXPECT_EQ(-1, delegate_->clicked_button_index()); - EXPECT_EQ(base::string16(), delegate_->submitted_reply_string()); + EXPECT_EQ(std::u16string(), delegate_->submitted_reply_string()); // Click the button again and focus on the inline textfield. generator.ClickLeftButton(); @@ -695,14 +695,14 @@ TEST_F(NotificationViewMDTest, TestInlineReply) { generator.MoveMouseTo(cursor_location); generator.ClickLeftButton(); EXPECT_EQ(1, delegate_->clicked_button_index()); - EXPECT_EQ(base::ASCIIToUTF16("test"), delegate_->submitted_reply_string()); + EXPECT_EQ(u"test", delegate_->submitted_reply_string()); } TEST_F(NotificationViewMDTest, TestInlineReplyRemovedByUpdate) { std::unique_ptr notification = CreateSimpleNotification(); std::vector buttons = CreateButtons(2); - buttons[1].placeholder = base::string16(); + buttons[1].placeholder = std::u16string(); notification->set_buttons(buttons); UpdateNotificationViews(*notification); notification_view()->GetWidget()->Show(); @@ -752,7 +752,7 @@ TEST_F(NotificationViewMDTest, TestInlineReplyActivateWithKeyPress) { std::unique_ptr notification = CreateSimpleNotification(); std::vector buttons = CreateButtons(2); - buttons[1].placeholder = base::string16(); + buttons[1].placeholder = std::u16string(); notification->set_buttons(buttons); UpdateNotificationViews(*notification); notification_view()->GetWidget()->Show(); @@ -929,8 +929,7 @@ TEST_F(NotificationViewMDTest, SnoozeButton) { rich_data.should_show_snooze_button = true; std::unique_ptr notification = std::make_unique( message_center::NOTIFICATION_TYPE_CUSTOM, kDefaultNotificationId, - base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message"), gfx::Image(), - base::UTF8ToUTF16("display source"), GURL(), + u"title", u"message", gfx::Image(), u"display source", GURL(), message_center::NotifierId(message_center::NotifierType::ARC_APPLICATION, "test_app_id"), rich_data, nullptr); @@ -950,7 +949,7 @@ TEST_F(NotificationViewMDTest, ExpandLongMessage) { // message_view_. // Without doing this, inappropriate fix such as // message_view_->GetPreferredSize() returning gfx::Size() can pass. - notification->set_title(base::string16()); + 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 " @@ -993,8 +992,10 @@ TEST_F(NotificationViewMDTest, ExpandLongMessage) { } TEST_F(NotificationViewMDTest, TestAccentColor) { + // TODO(pkasting): These hardcoded colors are fragile and should be obtained + // dynamically. const SkColor kNotificationBackgroundColor = SK_ColorWHITE; - const SkColor kActionButtonBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE); + const SkColor kActionButtonBackgroundColor = SkColorSetRGB(0xF2, 0xF2, 0xF2); const SkColor kActionButtonTextColor = DeriveMinContrastColor(gfx::kGoogleBlue600, kActionButtonBackgroundColor); @@ -1003,7 +1004,12 @@ TEST_F(NotificationViewMDTest, TestAccentColor) { std::unique_ptr notification = CreateSimpleNotification(); notification->set_buttons(CreateButtons(2)); + + // The code below is not prepared to deal with dark mode. + notification_view()->GetWidget()->GetNativeTheme()->set_use_dark_colors( + false); UpdateNotificationViews(*notification); + notification_view()->GetWidget()->Show(); // Action buttons are hidden by collapsed state. @@ -1011,9 +1017,18 @@ TEST_F(NotificationViewMDTest, TestAccentColor) { notification_view()->ToggleExpanded(); EXPECT_TRUE(notification_view()->actions_row_->GetVisible()); + auto* theme = notification_view()->GetNativeTheme(); auto app_icon_color_matches = [&](SkColor color) { SkBitmap expected = - notification->GenerateMaskedSmallIcon(kSmallImageSizeMD, color) + notification + ->GenerateMaskedSmallIcon( + kSmallImageSizeMD, color, + theme->GetSystemColor( + ui::NativeTheme:: + kColorId_MessageCenterSmallImageMaskBackground), + theme->GetSystemColor( + ui::NativeTheme:: + kColorId_MessageCenterSmallImageMaskForeground)) .AsBitmap(); SkBitmap actual = *notification_view() ->header_row_->app_icon_view_for_testing() @@ -1358,7 +1373,7 @@ TEST_F(NotificationViewMDTest, TestClickExpanded) { TEST_F(NotificationViewMDTest, TestDeleteOnToggleExpanded) { std::unique_ptr notification = CreateSimpleNotification(); notification->set_type(NotificationType::NOTIFICATION_TYPE_SIMPLE); - notification->set_title(base::string16()); + 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 " @@ -1390,7 +1405,7 @@ TEST_F(NotificationViewMDTest, TestDeleteOnDisableNotification) { TEST_F(NotificationViewMDTest, TestLongTitleAndMessage) { std::unique_ptr notification = CreateSimpleNotification(); notification->set_type(NotificationType::NOTIFICATION_TYPE_SIMPLE); - notification->set_title(base::ASCIIToUTF16("title")); + 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 " @@ -1412,7 +1427,7 @@ TEST_F(NotificationViewMDTest, TestLongTitleAndMessage) { } TEST_F(NotificationViewMDTest, AppNameExtension) { - base::string16 app_name = base::UTF8ToUTF16("extension name"); + std::u16string app_name = u"extension name"; std::unique_ptr notification = CreateSimpleNotification(); notification->set_context_message(app_name); @@ -1422,14 +1437,13 @@ TEST_F(NotificationViewMDTest, AppNameExtension) { } TEST_F(NotificationViewMDTest, AppNameSystemNotification) { - base::string16 app_name = base::UTF8ToUTF16("system notification"); + std::u16string app_name = u"system notification"; message_center::MessageCenter::Get()->SetSystemNotificationAppName(app_name); RichNotificationData data; data.settings_button_handler = SettingsButtonHandler::INLINE; auto notification = std::make_unique( NOTIFICATION_TYPE_BASE_FORMAT, std::string(kDefaultNotificationId), - base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message"), gfx::Image(), - base::string16(), GURL(), + u"title", u"message", gfx::Image(), std::u16string(), GURL(), NotifierId(NotifierType::SYSTEM_COMPONENT, "system"), data, nullptr); UpdateNotificationViews(*notification); @@ -1443,7 +1457,7 @@ TEST_F(NotificationViewMDTest, AppNameWebNotification) { UpdateNotificationViews(*notification); - EXPECT_EQ(base::UTF8ToUTF16("example.com"), + EXPECT_EQ(u"example.com", notification_view()->header_row_->app_name_for_testing()); } diff --git a/chromium/ui/message_center/views/padded_button.cc b/chromium/ui/message_center/views/padded_button.cc index 0972f1caa62..531992e4301 100644 --- a/chromium/ui/message_center/views/padded_button.cc +++ b/chromium/ui/message_center/views/padded_button.cc @@ -8,6 +8,7 @@ #include "build/chromeos_buildflags.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/color_utils.h" #include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/native_theme/native_theme.h" #include "ui/views/animation/ink_drop.h" @@ -41,11 +42,14 @@ void PaddedButton::OnThemeChanged() { ImageButton::OnThemeChanged(); auto* theme = GetNativeTheme(); #if BUILDFLAG(IS_CHROMEOS_ASH) - SetBackground(views::CreateSolidBackground(theme->GetSystemColor( - ui::NativeTheme::kColorId_NotificationButtonBackground))); + SkColor background_color = theme->GetSystemColor( + ui::NativeTheme::kColorId_NotificationButtonBackground); + SetBackground(views::CreateSolidBackground(background_color)); +#else + SkColor background_color = + theme->GetSystemColor(ui::NativeTheme::kColorId_WindowBackground); #endif - SetInkDropBaseColor(theme->GetSystemColor( - ui::NativeTheme::kColorId_PaddedButtonInkDropColor)); + SetInkDropBaseColor(color_utils::GetColorWithMaxContrast(background_color)); } BEGIN_METADATA(PaddedButton, views::ImageButton) diff --git a/chromium/ui/message_center/views/relative_time_formatter.cc b/chromium/ui/message_center/views/relative_time_formatter.cc index 6053884bf5f..46eba0b18fc 100644 --- a/chromium/ui/message_center/views/relative_time_formatter.cc +++ b/chromium/ui/message_center/views/relative_time_formatter.cc @@ -56,7 +56,7 @@ const RelativeTimeFormat& GetRelativeTimeFormat(TimeDelta delta) { } // namespace void GetRelativeTimeStringAndNextUpdateTime(TimeDelta delta, - base::string16* relative_time, + std::u16string* relative_time, TimeDelta* next_update) { bool past = delta < TimeDelta(); TimeDelta absolute = past ? -delta : delta; diff --git a/chromium/ui/message_center/views/relative_time_formatter.h b/chromium/ui/message_center/views/relative_time_formatter.h index d43f60994f5..ab760e83ef6 100644 --- a/chromium/ui/message_center/views/relative_time_formatter.h +++ b/chromium/ui/message_center/views/relative_time_formatter.h @@ -5,7 +5,8 @@ #ifndef UI_MESSAGE_CENTER_VIEWS_RELATIVE_TIME_FORMATTER_H_ #define UI_MESSAGE_CENTER_VIEWS_RELATIVE_TIME_FORMATTER_H_ -#include "base/strings/string16.h" +#include + #include "base/time/time.h" #include "ui/message_center/message_center_export.h" @@ -16,7 +17,7 @@ namespace message_center { // written to |next_update|. MESSAGE_CENTER_EXPORT void GetRelativeTimeStringAndNextUpdateTime( base::TimeDelta delta, - base::string16* relative_time, + std::u16string* relative_time, base::TimeDelta* next_update); } // namespace message_center diff --git a/chromium/ui/message_center/views/relative_time_formatter_unittest.cc b/chromium/ui/message_center/views/relative_time_formatter_unittest.cc index e5ec268cbcf..b9a4524357c 100644 --- a/chromium/ui/message_center/views/relative_time_formatter_unittest.cc +++ b/chromium/ui/message_center/views/relative_time_formatter_unittest.cc @@ -18,15 +18,15 @@ namespace { // In Android, DateUtils.YEAR_IN_MILLIS is 364 days (52 weeks * 7 days). constexpr TimeDelta kYearTimeDelta = TimeDelta::FromDays(364); -base::string16 GetRelativeTime(TimeDelta delta) { - base::string16 relative_time; +std::u16string GetRelativeTime(TimeDelta delta) { + std::u16string relative_time; TimeDelta next_update; GetRelativeTimeStringAndNextUpdateTime(delta, &relative_time, &next_update); return relative_time; } TimeDelta GetNextUpdate(TimeDelta delta) { - base::string16 relative_time; + std::u16string relative_time; TimeDelta next_update; GetRelativeTimeStringAndNextUpdateTime(delta, &relative_time, &next_update); return next_update; @@ -35,112 +35,112 @@ TimeDelta GetNextUpdate(TimeDelta delta) { } // namespace TEST(RelativeTimeFormatterTest, Format_Future_30Sec) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromSeconds(30)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromSeconds(30)); EXPECT_EQ( l10n_util::GetStringUTF16(IDS_MESSAGE_NOTIFICATION_NOW_STRING_SHORTEST), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_30Sec) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromSeconds(-30)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromSeconds(-30)); EXPECT_EQ( l10n_util::GetStringUTF16(IDS_MESSAGE_NOTIFICATION_NOW_STRING_SHORTEST), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_60Sec) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromMinutes(1)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromMinutes(1)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST_FUTURE, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_60Sec) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromMinutes(-1)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromMinutes(-1)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_5Min) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromMinutes(5)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromMinutes(5)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST_FUTURE, 5), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_5Min) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromMinutes(-5)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromMinutes(-5)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_MINUTES_SHORTEST, 5), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_60Min) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromHours(1)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromHours(1)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_60Min) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromHours(-1)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromHours(-1)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_10Hrs) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromHours(10)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromHours(10)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE, 10), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_10Hrs) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromHours(-10)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromHours(-10)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST, 10), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_24Hrs) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromDays(1)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromDays(1)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST_FUTURE, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_24Hrs) { - base::string16 relative_time = GetRelativeTime(TimeDelta::FromDays(-1)); + std::u16string relative_time = GetRelativeTime(TimeDelta::FromDays(-1)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_DAYS_SHORTEST, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_1Year) { - base::string16 relative_time = GetRelativeTime(kYearTimeDelta); + std::u16string relative_time = GetRelativeTime(kYearTimeDelta); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST_FUTURE, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_1Year) { - base::string16 relative_time = GetRelativeTime(-kYearTimeDelta); + std::u16string relative_time = GetRelativeTime(-kYearTimeDelta); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST, 1), relative_time); } TEST(RelativeTimeFormatterTest, Format_Future_10Years) { - base::string16 relative_time = GetRelativeTime(kYearTimeDelta * 10); + std::u16string relative_time = GetRelativeTime(kYearTimeDelta * 10); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST_FUTURE, 10), relative_time); } TEST(RelativeTimeFormatterTest, Format_Past_10Years) { - base::string16 relative_time = GetRelativeTime(-kYearTimeDelta * 10); + std::u16string relative_time = GetRelativeTime(-kYearTimeDelta * 10); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_YEARS_SHORTEST, 10), relative_time); diff --git a/chromium/ui/native_theme/BUILD.gn b/chromium/ui/native_theme/BUILD.gn index 2f5cc7d7cde..23db59833ce 100644 --- a/chromium/ui/native_theme/BUILD.gn +++ b/chromium/ui/native_theme/BUILD.gn @@ -21,6 +21,8 @@ component("native_theme") { "native_theme_features.h", "native_theme_observer.cc", "native_theme_observer.h", + "native_theme_utils.cc", + "native_theme_utils.h", "themed_vector_icon.cc", "themed_vector_icon.h", ] @@ -33,6 +35,11 @@ component("native_theme") { } if (is_mac) { + frameworks = [ + "CoreGraphics.framework", + "AppKit.framework", + "MediaAccessibility.framework", + ] sources += [ "caption_style_mac.mm", "native_theme_mac.h", @@ -71,14 +78,6 @@ component("native_theme") { "//ui/gfx/geometry", "//ui/resources", ] - - if (is_mac) { - frameworks = [ - "CoreGraphics.framework", - "AppKit.framework", - "MediaAccessibility.framework", - ] - } } if (is_win) { @@ -116,6 +115,8 @@ source_set("test_support") { ] sources = [ + "test/color_utils.cc", + "test/color_utils.h", "test_native_theme.cc", "test_native_theme.h", ] @@ -133,10 +134,6 @@ test("native_theme_unittests") { sources += [ "native_theme_aura_unittest.cc" ] } - if (is_mac) { - sources += [ "native_theme_mac_unittest.mm" ] - } - if (is_win) { sources += [ "caption_style_win_unittest.cc", @@ -147,6 +144,7 @@ test("native_theme_unittests") { deps = [ ":native_theme", ":native_theme_browser", + ":test_support", "//base/test:run_all_unittests", "//base/test:test_support", "//skia", @@ -154,4 +152,9 @@ test("native_theme_unittests") { "//ui/base", "//ui/gfx/geometry:geometry", ] + + if (is_mac) { + sources += [ "native_theme_mac_unittest.mm" ] + deps += [ "//ui/color" ] + } } diff --git a/chromium/ui/native_theme/OWNERS b/chromium/ui/native_theme/OWNERS index 23e41d0051c..402f93c8d1c 100644 --- a/chromium/ui/native_theme/OWNERS +++ b/chromium/ui/native_theme/OWNERS @@ -1,3 +1,4 @@ ellyjones@chromium.org estade@chromium.org pkasting@chromium.org +tluk@chromium.org diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc index 8eef16d01a9..cdd49c092b6 100644 --- a/chromium/ui/native_theme/common_theme.cc +++ b/chromium/ui/native_theme/common_theme.cc @@ -4,42 +4,30 @@ #include "ui/native_theme/common_theme.h" +#include "base/containers/fixed_flat_map.h" +#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/skia/include/core/SkCanvas.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/color/color_provider_utils.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/skia_util.h" +#include "ui/native_theme/native_theme_utils.h" #include "ui/native_theme/overlay_scrollbar_constants_aura.h" namespace ui { namespace { -NativeTheme::SecurityChipColorId GetSecurityChipColorId( - NativeTheme::ColorId color_id) { - static const base::NoDestructor< - base::flat_map> - color_id_map({ - {NativeTheme::kColorId_CustomTabBarSecurityChipDefaultColor, - NativeTheme::SecurityChipColorId::DEFAULT}, - {NativeTheme::kColorId_CustomTabBarSecurityChipSecureColor, - NativeTheme::SecurityChipColorId::SECURE}, - {NativeTheme::kColorId_CustomTabBarSecurityChipWithCertColor, - NativeTheme::SecurityChipColorId::SECURE_WITH_CERT}, - {NativeTheme::kColorId_CustomTabBarSecurityChipDangerousColor, - NativeTheme::SecurityChipColorId::DANGEROUS}, - }); - return color_id_map->at(color_id); -} - base::Optional GetHighContrastColor( NativeTheme::ColorId color_id, NativeTheme::ColorScheme color_scheme) { @@ -64,36 +52,25 @@ base::Optional GetHighContrastColor( } } -base::Optional GetDarkSchemeColor(NativeTheme::ColorId color_id) { +base::Optional GetDarkSchemeColor(NativeTheme::ColorId color_id, + const NativeTheme* base_theme) { switch (color_id) { // Alert case NativeTheme::kColorId_AlertSeverityLow: - return gfx::kGoogleGreen300; case NativeTheme::kColorId_AlertSeverityHigh: - return gfx::kGoogleRed300; - case NativeTheme::kColorId_AlertSeverityMedium: - return gfx::kGoogleYellow300; + case NativeTheme::kColorId_AlertSeverityMedium: { + auto provider_color_id = NativeThemeColorIdToColorId(color_id); + DCHECK(provider_color_id); + return GetAlertSeverityColor(provider_color_id.value(), true); + } - // Bubble - case NativeTheme::kColorId_FootnoteContainerBorder: - return gfx::kGoogleGrey900; + // Border + case NativeTheme::kColorId_FocusedBorderColor: + return gfx::kGoogleBlue400; // Button - case NativeTheme::kColorId_ButtonInkDropShadowColor: - return SkColorSetA(SK_ColorBLACK, 0x7F); - case NativeTheme::kColorId_ButtonHoverColor: - return SkColorSetA(SK_ColorBLACK, 0x0A); - case NativeTheme::kColorId_ButtonInkDropFillColor: - case NativeTheme::kColorId_ProminentButtonHoverColor: - return SkColorSetA(SK_ColorWHITE, 0x0A); case NativeTheme::kColorId_ProminentButtonColor: return gfx::kGoogleBlue300; - case NativeTheme::kColorId_ProminentButtonInkDropShadowColor: - return SkColorSetA(gfx::kGoogleBlue300, 0x7F); - - // Custom tab bar - case NativeTheme::kColorId_CustomTabBarBackgroundColor: - return gfx::kGoogleGrey900; // Frame case NativeTheme::kColorId_CustomFrameActiveColor: @@ -106,32 +83,38 @@ base::Optional GetDarkSchemeColor(NativeTheme::ColorId color_id) { return gfx::kGoogleGrey500; case NativeTheme::kColorId_LabelEnabledColor: return gfx::kGoogleGrey200; - case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: - return gfx::kGoogleBlue800; - - // Menu - case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: - return SkColorSetRGB(0x32, 0x36, 0x39); // Separator case NativeTheme::kColorId_SeparatorColor: return gfx::kGoogleGrey800; - // Tabbed pane - case NativeTheme::kColorId_TabHighlightFocusedBackground: - return SkColorSetRGB(0x32, 0x36, 0x39); - case NativeTheme::kColorId_TabHighlightBackground: - return gfx::kGoogleGrey800; - - // Tooltip - case NativeTheme::kColorId_TooltipIcon: - return SkColorSetA(gfx::kGoogleGrey200, 0xBD); - case NativeTheme::kColorId_TooltipIconHovered: - return SK_ColorWHITE; + // Toggle button + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOff: { + const SkColor enabled = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, + NativeTheme::ColorScheme::kDark); + const SkColor secondary = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, + NativeTheme::ColorScheme::kDark); + return color_utils::AlphaBlend(enabled, secondary, SkAlpha{0x0D}); + } + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOn: { + const SkColor enabled = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, + NativeTheme::ColorScheme::kDark); + const SkColor prominent = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, + NativeTheme::ColorScheme::kDark); + return color_utils::AlphaBlend(enabled, prominent, SkAlpha{0x0D}); + } + case ui::NativeTheme::kColorId_ToggleButtonTrackColorOff: + return gfx::kGoogleGrey700; + case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: + return gfx::kGoogleBlue600; // Window case NativeTheme::kColorId_WindowBackground: - return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900, 0.04f); + return color_utils::BlendTowardMaxContrast(gfx::kGoogleGrey900, 0x0A); default: return base::nullopt; @@ -144,160 +127,137 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id, switch (color_id) { // Alert case NativeTheme::kColorId_AlertSeverityLow: - return gfx::kGoogleGreen700; case NativeTheme::kColorId_AlertSeverityHigh: - return gfx::kGoogleRed600; - case NativeTheme::kColorId_AlertSeverityMedium: - return gfx::kGoogleYellow700; + case NativeTheme::kColorId_AlertSeverityMedium: { + auto provider_color_id = NativeThemeColorIdToColorId(color_id); + DCHECK(provider_color_id); + return GetAlertSeverityColor(provider_color_id.value(), false); + } // Avatar case NativeTheme::kColorId_AvatarHeaderArt: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); case NativeTheme::kColorId_AvatarIconGuest: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_AvatarIconIncognito: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); // Border case NativeTheme::kColorId_UnfocusedBorderColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); - case NativeTheme::kColorId_FocusedBorderColor: { - const SkColor accent = base_theme->GetSystemColor( - NativeTheme::kColorId_ProminentButtonColor, color_scheme); - return SkColorSetA(accent, 0x4D); - } + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); + case NativeTheme::kColorId_FocusedBorderColor: + return gfx::kGoogleBlue500; // Bubble case NativeTheme::kColorId_BubbleBackground: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); case NativeTheme::kColorId_BubbleFooterBackground: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, color_scheme); case NativeTheme::kColorId_FootnoteContainerBorder: - return gfx::kGoogleGrey200; case NativeTheme::kColorId_BubbleBorder: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); // Button case NativeTheme::kColorId_ButtonColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); case NativeTheme::kColorId_TextOnProminentButtonColor: - return color_utils::GetColorWithMaxContrast(base_theme->GetSystemColor( - NativeTheme::kColorId_ProminentButtonColor, color_scheme)); - case NativeTheme::kColorId_ProminentButtonHoverColor: - return SkColorSetA(SK_ColorWHITE, 0x0D); - case NativeTheme::kColorId_ProminentButtonInkDropFillColor: - return base_theme->GetSystemColor( - NativeTheme::kColorId_ProminentButtonHoverColor, color_scheme); - case NativeTheme::kColorId_ButtonInkDropFillColor: - return SkColorSetA(SK_ColorWHITE, 0x05); + return color_utils::GetColorWithMaxContrast( + base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme)); case NativeTheme::kColorId_ProminentButtonDisabledColor: - case NativeTheme::kColorId_DisabledButtonBorderColor: { - const SkColor bg = base_theme->GetSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendForMinContrast(bg, bg, base::nullopt, 1.2f) - .color; - } + case NativeTheme::kColorId_DisabledButtonBorderColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, + color_scheme); case NativeTheme::kColorId_ButtonBorderColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); case NativeTheme::kColorId_ButtonDisabledColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelDisabledColor, color_scheme); case NativeTheme::kColorId_ButtonUncheckedColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); - case NativeTheme::kColorId_PaddedButtonInkDropColor: - return color_utils::GetColorWithMaxContrast(base_theme->GetSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme)); - case NativeTheme::kColorId_ButtonHoverColor: - return SkColorSetA(SK_ColorBLACK, 0x05); - case NativeTheme::kColorId_ButtonInkDropShadowColor: - return SkColorSetA(SK_ColorBLACK, gfx::kGoogleGreyAlpha200); - case NativeTheme::kColorId_ProminentButtonInkDropShadowColor: - return SkColorSetA(SK_ColorBLACK, 0x3D); - case NativeTheme::kColorId_ProminentButtonFocusedColor: { - const SkColor bg = base_theme->GetSystemColor( - NativeTheme::kColorId_ProminentButtonColor, color_scheme); - return color_utils::BlendForMinContrast(bg, bg, base::nullopt, 1.3f) - .color; - } case NativeTheme::kColorId_ButtonCheckedColor: case NativeTheme::kColorId_ButtonEnabledColor: - return base_theme->GetSystemColor( + case NativeTheme::kColorId_ProminentButtonFocusedColor: + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme); case NativeTheme::kColorId_ProminentButtonColor: return gfx::kGoogleBlue600; // Custom tab bar - case NativeTheme::kColorId_CustomTabBarBackgroundColor: - return SK_ColorWHITE; - case NativeTheme::kColorId_CustomTabBarForegroundColor: - return color_utils::GetColorWithMaxContrast(base_theme->GetSystemColor( - NativeTheme::kColorId_CustomTabBarBackgroundColor, color_scheme)); + case NativeTheme::kColorId_CustomTabBarBackgroundColor: { + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_CustomTabBarForegroundColor, color_scheme); + return color_utils::GetColorWithMaxContrast(fg); + } + case NativeTheme::kColorId_CustomTabBarForegroundColor: { + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + return color_utils::GetColorWithMaxContrast(fg); + } case NativeTheme::kColorId_CustomTabBarSecurityChipWithCertColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelDisabledColor, color_scheme); case NativeTheme::kColorId_CustomTabBarSecurityChipSecureColor: case NativeTheme::kColorId_CustomTabBarSecurityChipDefaultColor: - case NativeTheme::kColorId_CustomTabBarSecurityChipDangerousColor: { - const SkColor fg = base_theme->GetSystemColor( - NativeTheme::kColorId_CustomTabBarForegroundColor, color_scheme); - const SkColor bg = base_theme->GetSystemColor( - NativeTheme::kColorId_CustomTabBarBackgroundColor, color_scheme); - return GetSecurityChipColor(GetSecurityChipColorId(color_id), fg, bg); - } + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); + case NativeTheme::kColorId_CustomTabBarSecurityChipDangerousColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_AlertSeverityHigh, color_scheme); // Dialog case NativeTheme::kColorId_DialogBackground: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); case NativeTheme::kColorId_DialogForeground: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); // Dropdown case NativeTheme::kColorId_DropdownBackgroundColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); - case NativeTheme::kColorId_DropdownSelectedBackgroundColor: { - const SkColor bg = base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendForMinContrast(bg, bg, base::nullopt, 1.67f) - .color; - } + case NativeTheme::kColorId_DropdownSelectedBackgroundColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_FocusedMenuItemBackgroundColor, color_scheme); case NativeTheme::kColorId_DropdownForegroundColor: case NativeTheme::kColorId_DropdownSelectedForegroundColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); // Frame case NativeTheme::kColorId_CustomFrameActiveColor: return SkColorSetRGB(0xDE, 0xE1, 0xE6); case NativeTheme::kColorId_CustomFrameInactiveColor: - return SkColorSetRGB(0xE7, 0xEA, 0xED); + return gfx::kGoogleGrey200; // Icon case NativeTheme::kColorId_DefaultIconColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_DisabledIconColor: { - const SkColor icon = base_theme->GetSystemColor( - NativeTheme::kColorId_LabelSecondaryColor, color_scheme); + const SkColor icon = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_DefaultIconColor, color_scheme); return SkColorSetA(icon, gfx::kDisabledControlAlpha); } // Label case NativeTheme::kColorId_LabelDisabledColor: { - const SkColor bg = base_theme->GetSystemColor( + const SkColor bg = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_WindowBackground, color_scheme); - const SkColor fg = base_theme->GetSystemColor( + const SkColor fg = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelEnabledColor, color_scheme); return color_utils::BlendForMinContrast(gfx::kGoogleGrey600, bg, fg) .color; @@ -306,50 +266,65 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id, return gfx::kGoogleGrey700; case NativeTheme::kColorId_LabelEnabledColor: return gfx::kGoogleGrey900; - case NativeTheme::kColorId_LabelTextSelectionColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); - case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: - return gfx::kGoogleBlue200; + case NativeTheme::kColorId_LabelTextSelectionColor: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelTextSelectionBackgroundFocused, + color_scheme); + return color_utils::GetColorWithMaxContrast(bg); + } + case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + return color_utils::AlphaBlend(fg, bg, gfx::kGoogleGreyAlpha500); + } // Link case NativeTheme::kColorId_LinkDisabled: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelDisabledColor, color_scheme); case NativeTheme::kColorId_LinkEnabled: case NativeTheme::kColorId_LinkPressed: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme); // Menu case NativeTheme::kColorId_MenuBackgroundColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); - case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: - return gfx::kGoogleGrey050; + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + return color_utils::BlendTowardMaxContrast(bg, gfx::kGoogleGreyAlpha100); + } case NativeTheme::kColorId_MenuBorderColor: case NativeTheme::kColorId_MenuSeparatorColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); - case NativeTheme::kColorId_FocusedMenuItemBackgroundColor: - return base_theme->GetSystemColor( - NativeTheme::kColorId_DropdownSelectedBackgroundColor, color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); + case NativeTheme::kColorId_FocusedMenuItemBackgroundColor: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_CustomTabBarForegroundColor, color_scheme); + return color_utils::AlphaBlend(fg, bg, gfx::kGoogleGreyAlpha200); + } case NativeTheme::kColorId_DisabledMenuItemForegroundColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelDisabledColor, color_scheme); case NativeTheme::kColorId_MenuIconColor: case NativeTheme::kColorId_MenuItemMinorTextColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_EnabledMenuItemForegroundColor: case NativeTheme::kColorId_HighlightedMenuItemForegroundColor: case NativeTheme::kColorId_MenuDropIndicator: case NativeTheme::kColorId_SelectedMenuItemForegroundColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); case NativeTheme::kColorId_MenuItemInitialAlertBackgroundColor: case NativeTheme::kColorId_MenuItemTargetAlertBackgroundColor: { - const SkColor accent = base_theme->GetSystemColor( + const SkColor accent = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme); constexpr auto kInitial = NativeTheme::kColorId_MenuItemInitialAlertBackgroundColor; @@ -358,41 +333,55 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id, } // Notification - case NativeTheme::kColorId_NotificationDefaultBackground: - case NativeTheme::kColorId_NotificationPlaceholderIconColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); + case NativeTheme::kColorId_MessageCenterSmallImageMaskForeground: + case NativeTheme::kColorId_NotificationBackground: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); #if BUILDFLAG(IS_CHROMEOS_ASH) case NativeTheme::kColorId_NotificationButtonBackground: return SkColorSetA(SK_ColorWHITE, 0.9 * 0xff); #endif - case NativeTheme::kColorId_NotificationEmptyPlaceholderTextColor: - return SkColorSetA(SK_ColorWHITE, gfx::kDisabledControlAlpha); - case NativeTheme::kColorId_NotificationEmptyPlaceholderIconColor: - return SkColorSetA(SK_ColorWHITE, 0x60); - case NativeTheme::kColorId_NotificationActionsRowBackground: - case NativeTheme::kColorId_NotificationInlineSettingsBackground: { - const SkColor bg = base_theme->GetSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendTowardMaxContrast(bg, 0x14); - } - case NativeTheme::kColorId_NotificationLargeImageBackground: { - const SkColor bg = base_theme->GetSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendTowardMaxContrast(bg, 0x0C); + case NativeTheme::kColorId_NotificationPlaceholderColor: { + const SkColor color = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TextOnProminentButtonColor, color_scheme); + return SkColorSetA(color, gfx::kGoogleGreyAlpha700); } + case NativeTheme::kColorId_NotificationColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TextOnProminentButtonColor, color_scheme); + case NativeTheme::kColorId_NotificationActionsRowBackground: + case NativeTheme::kColorId_NotificationBackgroundActive: + case NativeTheme::kColorId_NotificationLargeImageBackground: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, + color_scheme); + case NativeTheme::kColorId_MessageCenterSmallImageMaskBackground: case NativeTheme::kColorId_NotificationDefaultAccentColor: - return gfx::kGoogleGrey700; + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_NotificationInkDropBase: - return gfx::kGoogleBlue600; + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); // Scrollbar - case NativeTheme::kColorId_OverlayScrollbarThumbForeground: - return SkColorSetA(SK_ColorWHITE, (kOverlayScrollbarStrokeNormalAlpha / - kOverlayScrollbarThumbNormalAlpha) * - SK_AlphaOPAQUE); - case NativeTheme::kColorId_OverlayScrollbarThumbBackground: - return SK_ColorBLACK; + case NativeTheme::kColorId_OverlayScrollbarThumbFill: + case NativeTheme::kColorId_OverlayScrollbarThumbHoveredFill: { + const SkColor fill = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_CustomTabBarForegroundColor, color_scheme); + const bool hovered = + color_id == NativeTheme::kColorId_OverlayScrollbarThumbHoveredFill; + return SkColorSetA( + fill, hovered ? gfx::kGoogleGreyAlpha800 : gfx::kGoogleGreyAlpha700); + } + case NativeTheme::kColorId_OverlayScrollbarThumbStroke: + case NativeTheme::kColorId_OverlayScrollbarThumbHoveredStroke: { + const SkColor stroke = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_CustomTabBarBackgroundColor, color_scheme); + const bool hovered = + color_id == NativeTheme::kColorId_OverlayScrollbarThumbHoveredStroke; + return SkColorSetA(stroke, hovered ? gfx::kGoogleGreyAlpha500 + : gfx::kGoogleGreyAlpha400); + } // Separator case NativeTheme::kColorId_SeparatorColor: @@ -400,143 +389,163 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id, // Slider case NativeTheme::kColorId_SliderThumbMinimal: - return SkColorSetA(gfx::kGoogleGrey100, gfx::kGoogleGreyAlpha500); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_SliderTroughMinimal: - return SkColorSetA(gfx::kGoogleGrey100, 0x19); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); case NativeTheme::kColorId_SliderThumbDefault: - return gfx::kGoogleBlueDark600; - case NativeTheme::kColorId_SliderTroughDefault: - return SkColorSetA(gfx::kGoogleBlueDark600, 0x40); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + case NativeTheme::kColorId_SliderTroughDefault: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + return color_utils::AlphaBlend(fg, bg, gfx::kGoogleGreyAlpha400); + } // Sync info container case NativeTheme::kColorId_SyncInfoContainerNoPrimaryAccount: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, color_scheme); - case NativeTheme::kColorId_SyncInfoContainerPaused: - return SkColorSetA( - base_theme->GetSystemColor(NativeTheme::kColorId_ProminentButtonColor, - color_scheme), - 0x10); - case NativeTheme::kColorId_SyncInfoContainerError: - return SkColorSetA( - base_theme->GetSystemColor(NativeTheme::kColorId_AlertSeverityHigh, - color_scheme), - 0x10); + case NativeTheme::kColorId_SyncInfoContainerPaused: { + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + return SkColorSetA(fg, gfx::kGoogleGreyAlpha100); + } + case NativeTheme::kColorId_SyncInfoContainerError: { + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_AlertSeverityHigh, color_scheme); + return SkColorSetA(fg, gfx::kGoogleGreyAlpha100); + } // Tabbed pane case NativeTheme::kColorId_TabBottomBorder: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); case NativeTheme::kColorId_TabTitleColorInactive: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_TabHighlightBackground: - return gfx::kGoogleBlue050; + return SkColorSetA(gfx::kGoogleBlue300, 0x2B); case NativeTheme::kColorId_TabHighlightFocusedBackground: - return gfx::kGoogleBlue100; + return SkColorSetA(gfx::kGoogleBlue300, 0x53); case NativeTheme::kColorId_TabTitleColorActive: case NativeTheme::kColorId_TabSelectedBorderColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme); // Table case NativeTheme::kColorId_TableBackground: case NativeTheme::kColorId_TableBackgroundAlternate: case NativeTheme::kColorId_TableHeaderBackground: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); case NativeTheme::kColorId_TableGroupingIndicatorColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_FocusedBorderColor, color_scheme); case NativeTheme::kColorId_TableSelectionBackgroundFocused: - case NativeTheme::kColorId_TableSelectionBackgroundUnfocused: - return base_theme->GetSystemColor( - NativeTheme::kColorId_DropdownSelectedBackgroundColor, color_scheme); + case NativeTheme::kColorId_TableSelectionBackgroundUnfocused: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + return color_utils::AlphaBlend(fg, bg, SkAlpha{0x3C}); + } case NativeTheme::kColorId_TableHeaderSeparator: - return base_theme->GetSystemColor(NativeTheme::kColorId_SeparatorColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); case NativeTheme::kColorId_TableHeaderText: case NativeTheme::kColorId_TableSelectedText: case NativeTheme::kColorId_TableSelectedTextUnfocused: case NativeTheme::kColorId_TableText: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); // Textfield case NativeTheme::kColorId_TextfieldReadOnlyBackground: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); - case NativeTheme::kColorId_TextfieldDefaultBackground: { - const SkColor fg = base_theme->GetSystemColor( - NativeTheme::kColorId_LabelEnabledColor, color_scheme); - return color_utils::GetColorWithMaxContrast(fg); - } + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + case NativeTheme::kColorId_TextfieldDefaultBackground: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_CustomTabBarBackgroundColor, color_scheme); case NativeTheme::kColorId_TextfieldPlaceholderColor: case NativeTheme::kColorId_TextfieldReadOnlyColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelDisabledColor, color_scheme); case NativeTheme::kColorId_TextfieldDefaultColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); case NativeTheme::kColorId_TextfieldSelectionColor: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelTextSelectionColor, color_scheme); case NativeTheme::kColorId_TextfieldSelectionBackgroundFocused: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelTextSelectionBackgroundFocused, color_scheme); // Throbber - case NativeTheme::kColorId_ThrobberLightColor: - return SkColorSetRGB(0xF4, 0xF8, 0xFD); case NativeTheme::kColorId_ThrobberWaitingColor: - return SkColorSetRGB(0xA6, 0xA6, 0xA6); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SliderTroughDefault, color_scheme); case NativeTheme::kColorId_ThrobberSpinningColor: - return base_theme->GetSystemColor( + return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme); // Toggle button case NativeTheme::kColorId_ToggleButtonShadowColor: - return SkColorSetA( - base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme), - 0x99); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOff: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOn: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); case ui::NativeTheme::kColorId_ToggleButtonTrackColorOff: - case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: { - const ui::NativeTheme::ColorId base_color_id = - color_id == ui::NativeTheme::kColorId_ToggleButtonTrackColorOff - ? ui::NativeTheme::kColorId_LabelEnabledColor - : ui::NativeTheme::kColorId_ProminentButtonColor; - return SkColorSetA( - base_theme->GetSystemColor(base_color_id, color_scheme), 0x66); - } + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); + case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: + return gfx::kGoogleBlue300; // Tooltip case NativeTheme::kColorId_TooltipBackground: { - const SkColor bg = base_theme->GetSystemColor( + const SkColor bg = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_WindowBackground, color_scheme); return SkColorSetA(bg, 0xCC); } - case NativeTheme::kColorId_TooltipIcon: - return SkColorSetA(gfx::kGoogleGrey800, 0xBD); case NativeTheme::kColorId_TooltipText: { - const SkColor text = base_theme->GetSystemColor( + const SkColor text = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelEnabledColor, color_scheme); return SkColorSetA(text, 0xDE); } + + // Tooltip icon + case NativeTheme::kColorId_TooltipIcon: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_TooltipIconHovered: - return SkColorSetA(SK_ColorBLACK, 0xBD); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); // Tree case NativeTheme::kColorId_TreeBackground: - return base_theme->GetSystemColor(NativeTheme::kColorId_WindowBackground, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); case NativeTheme::kColorId_TreeSelectionBackgroundFocused: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TableSelectionBackgroundFocused, color_scheme); case NativeTheme::kColorId_TreeSelectionBackgroundUnfocused: - return base_theme->GetSystemColor( - NativeTheme::kColorId_DropdownSelectedBackgroundColor, color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TableSelectionBackgroundUnfocused, + color_scheme); case NativeTheme::kColorId_TreeSelectedText: case NativeTheme::kColorId_TreeSelectedTextUnfocused: case NativeTheme::kColorId_TreeText: - return base_theme->GetSystemColor(NativeTheme::kColorId_LabelEnabledColor, - color_scheme); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); // Window case NativeTheme::kColorId_WindowBackground: @@ -553,37 +562,16 @@ SkColor GetDefaultColor(NativeTheme::ColorId color_id, } // namespace -SkColor GetSecurityChipColor(NativeTheme::SecurityChipColorId chip_color_id, - SkColor fg, - SkColor bg, - bool high_contrast) { - const bool dark = color_utils::IsDark(bg); - const auto blend_for_min_contrast = [&](SkColor fg, SkColor bg, - base::Optional hc_fg = - base::nullopt) { - const float ratio = - high_contrast ? 6.0f : color_utils::kMinimumReadableContrastRatio; - return color_utils::BlendForMinContrast(fg, bg, hc_fg, ratio).color; - }; - const auto security_chip_color = [&](SkColor color) { - return blend_for_min_contrast(color, bg); - }; - - switch (chip_color_id) { - case NativeTheme::SecurityChipColorId::DEFAULT: - case NativeTheme::SecurityChipColorId::SECURE: - return dark - ? color_utils::BlendTowardMaxContrast(fg, 0x18) - : security_chip_color(color_utils::DeriveDefaultIconColor(fg)); - case NativeTheme::SecurityChipColorId::DANGEROUS: - return dark ? color_utils::BlendTowardMaxContrast(fg, 0x18) - : security_chip_color(gfx::kGoogleRed600); - case NativeTheme::SecurityChipColorId::SECURE_WITH_CERT: - return blend_for_min_contrast(fg, fg, blend_for_min_contrast(bg, bg)); - default: - NOTREACHED(); - return gfx::kPlaceholderColor; - } +SkColor GetAlertSeverityColor(ColorId color_id, bool dark) { + constexpr auto kColorIdMap = + base::MakeFixedFlatMap>({ + {kColorAlertHighSeverity, {{gfx::kGoogleRed600, gfx::kGoogleRed300}}}, + {kColorAlertLowSeverity, + {{gfx::kGoogleGreen700, gfx::kGoogleGreen300}}}, + {kColorAlertMediumSeverity, + {{gfx::kGoogleYellow700, gfx::kGoogleYellow300}}}, + }); + return kColorIdMap.at(color_id)[dark]; } SkColor GetAuraColor(NativeTheme::ColorId color_id, @@ -597,17 +585,29 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id, if (base_theme->UserHasContrastPreference()) { base::Optional color = GetHighContrastColor(color_id, color_scheme); - if (color.has_value()) + if (color.has_value()) { + DVLOG(2) << "GetHighContrastColor: " + << "NativeTheme::ColorId: " << NativeThemeColorIdName(color_id) + << " Color: " << SkColorName(color.value()); return color.value(); + } } if (color_scheme == NativeTheme::ColorScheme::kDark) { - base::Optional color = GetDarkSchemeColor(color_id); - if (color.has_value()) + base::Optional color = GetDarkSchemeColor(color_id, base_theme); + if (color.has_value()) { + DVLOG(2) << "GetDarkSchemeColor: " + << "NativeTheme::ColorId: " << NativeThemeColorIdName(color_id) + << " Color: " << SkColorName(color.value()); return color.value(); + } } - return GetDefaultColor(color_id, base_theme, color_scheme); + SkColor color = GetDefaultColor(color_id, base_theme, color_scheme); + DVLOG(2) << "GetDefaultColor: " + << "NativeTheme::ColorId: " << NativeThemeColorIdName(color_id) + << " Color: " << SkColorName(color); + return color; } void CommonThemePaintMenuItemBackground( diff --git a/chromium/ui/native_theme/common_theme.h b/chromium/ui/native_theme/common_theme.h index 4c87d30f366..73a84cf1ac6 100644 --- a/chromium/ui/native_theme/common_theme.h +++ b/chromium/ui/native_theme/common_theme.h @@ -7,20 +7,19 @@ #include +#include "ui/color/color_id.h" #include "ui/native_theme/native_theme.h" - +#include "ui/native_theme/native_theme_export.h" namespace ui { // Drawing code that is common for all platforms. -// Takes a SecurityChipColorId and |fg| and |bg| colors so that the security -// chip color implementation can be shared outside of NativeTheme. -SkColor NATIVE_THEME_EXPORT -GetSecurityChipColor(NativeTheme::SecurityChipColorId chip_color_id, - SkColor fg, - SkColor bg, - bool high_contrast = false); +// Gets the appropriate alert severity color for light / dark mode. +// TODO(tluk): Create unique color ids for each use of the alert severity colors +// and update this function to take the background color over which the alert +// color is to be used. +SkColor NATIVE_THEME_EXPORT GetAlertSeverityColor(ColorId color_id, bool dark); // Returns the color to use on Aura for |color_id|. For a few colors that are // theme-specific, |base_theme| must be non-null; consult the code to see which diff --git a/chromium/ui/native_theme/native_theme.cc b/chromium/ui/native_theme/native_theme.cc index d4e2f30a563..998e819abb4 100644 --- a/chromium/ui/native_theme/native_theme.cc +++ b/chromium/ui/native_theme/native_theme.cc @@ -12,153 +12,20 @@ #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" +#include "base/optional.h" #include "build/build_config.h" #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/color/color_provider_manager.h" +#include "ui/color/color_provider_utils.h" #include "ui/native_theme/common_theme.h" - -#if !defined(OS_ANDROID) -#include "ui/color/color_mixers.h" -#endif +#include "ui/native_theme/native_theme_utils.h" namespace ui { namespace { -// clang-format off -bool NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id, - ColorId* color_id) { - using NTCID = NativeTheme::ColorId; - static constexpr const auto map = - base::MakeFixedFlatMap({ - {NTCID::kColorId_AlertSeverityHigh, kColorAlertHighSeverity}, - {NTCID::kColorId_AlertSeverityLow, kColorAlertLowSeverity}, - {NTCID::kColorId_AlertSeverityMedium, kColorAlertMediumSeverity}, - {NTCID::kColorId_AvatarHeaderArt, kColorAvatarHeaderArt}, - {NTCID::kColorId_AvatarIconGuest, kColorAvatarIconGuest}, - {NTCID::kColorId_AvatarIconIncognito, kColorAvatarIconIncognito}, - {NTCID::kColorId_BubbleBackground, kColorBubbleBackground}, - {NTCID::kColorId_BubbleFooterBackground, - kColorBubbleFooterBackground}, - {NTCID::kColorId_ButtonColor, kColorButtonBackground}, - {NTCID::kColorId_ButtonBorderColor, kColorButtonBorder}, - {NTCID::kColorId_DisabledButtonBorderColor, kColorButtonBorderDisabled}, - {NTCID::kColorId_ButtonDisabledColor, - kColorButtonForegroundDisabled}, - {NTCID::kColorId_ButtonEnabledColor, kColorButtonForeground}, - {NTCID::kColorId_ProminentButtonColor, - kColorButtonBackgroundProminent}, - {NTCID::kColorId_ProminentButtonDisabledColor, - kColorButtonBackgroundProminentDisabled}, - {NTCID::kColorId_ProminentButtonFocusedColor, - kColorButtonBackgroundProminentFocused}, - {NTCID::kColorId_TextOnProminentButtonColor, - kColorButtonForegroundProminent}, - {NTCID::kColorId_ButtonUncheckedColor, - kColorButtonForegroundUnchecked}, - {NTCID::kColorId_DialogBackground, kColorDialogBackground}, - {NTCID::kColorId_DialogForeground, kColorDialogForeground}, - {NTCID::kColorId_FocusedBorderColor, kColorFocusableBorderFocused}, - {NTCID::kColorId_UnfocusedBorderColor, - kColorFocusableBorderUnfocused}, - {NTCID::kColorId_MenuIconColor, kColorMenuIcon}, - {NTCID::kColorId_DefaultIconColor, kColorIcon}, - {NTCID::kColorId_LabelDisabledColor, kColorLabelForegroundDisabled}, - {NTCID::kColorId_LabelEnabledColor, kColorLabelForeground}, - {NTCID::kColorId_LabelSecondaryColor, - kColorLabelForegroundSecondary}, - {NTCID::kColorId_LabelTextSelectionBackgroundFocused, - kColorLabelSelectionBackground}, - {NTCID::kColorId_LabelTextSelectionColor, - kColorLabelSelectionForeground}, - {NTCID::kColorId_LinkDisabled, kColorLinkForegroundDisabled}, - {NTCID::kColorId_LinkEnabled, kColorLinkForeground}, - {NTCID::kColorId_LinkPressed, kColorLinkForegroundPressed}, - {NTCID::kColorId_MenuBackgroundColor, kColorMenuBackground}, - {NTCID::kColorId_MenuBorderColor, kColorMenuBorder}, - {NTCID::kColorId_MenuItemInitialAlertBackgroundColor, - kColorMenuItemBackgroundAlertedInitial}, - {NTCID::kColorId_MenuItemTargetAlertBackgroundColor, - kColorMenuItemBackgroundAlertedTarget}, - {NTCID::kColorId_DisabledMenuItemForegroundColor, - kColorMenuItemForegroundDisabled}, - {NTCID::kColorId_EnabledMenuItemForegroundColor, - kColorMenuItemForeground}, - {NTCID::kColorId_HighlightedMenuItemBackgroundColor, - kColorMenuItemBackgroundHighlighted}, - {NTCID::kColorId_HighlightedMenuItemForegroundColor, - kColorMenuItemForegroundHighlighted}, - {NTCID::kColorId_MenuItemMinorTextColor, - kColorMenuItemForegroundSecondary}, - {NTCID::kColorId_FocusedMenuItemBackgroundColor, - kColorMenuItemBackgroundSelected}, - {NTCID::kColorId_SelectedMenuItemForegroundColor, - kColorMenuItemForegroundSelected}, - {NTCID::kColorId_MenuSeparatorColor, kColorMenuSeparator}, - {NTCID::kColorId_TabBottomBorder, kColorTabContentSeparator}, - {NTCID::kColorId_TabTitleColorInactive, kColorTabForeground}, - {NTCID::kColorId_TabSelectedBorderColor, kColorTabBorderSelected}, - {NTCID::kColorId_TabTitleColorActive, kColorTabForegroundSelected}, - {NTCID::kColorId_TableBackground, kColorTableBackground}, -#if defined(OS_APPLE) - {NTCID::kColorId_TableBackgroundAlternate, - kColorTableBackgroundAlternate}, -#endif - {NTCID::kColorId_TableText, kColorTableForeground}, - {NTCID::kColorId_TableGroupingIndicatorColor, - kColorTableGroupingIndicator}, - {NTCID::kColorId_TableHeaderBackground, - kColorTableHeaderBackground}, - {NTCID::kColorId_TableHeaderText, kColorTableHeaderForeground}, - // TODO(http://crbug.com/1057754): kColorId_TableHeaderSeparator, - // which is implemented as a native theme override on Mac. - {NTCID::kColorId_TableSelectionBackgroundFocused, - kColorTableBackgroundSelectedFocused}, - {NTCID::kColorId_TableSelectedText, - kColorTableForegroundSelectedFocused}, - {NTCID::kColorId_TableSelectionBackgroundUnfocused, - kColorTableBackgroundSelectedUnfocused}, - {NTCID::kColorId_TableSelectedTextUnfocused, - kColorTableForegroundSelectedUnfocused}, - {NTCID::kColorId_TextfieldDefaultBackground, - kColorTextfieldBackground}, - {NTCID::kColorId_TextfieldReadOnlyBackground, - kColorTextfieldBackgroundDisabled}, - {NTCID::kColorId_TextfieldReadOnlyColor, - kColorTextfieldForegroundDisabled}, - {NTCID::kColorId_TextfieldPlaceholderColor, - kColorTextfieldForegroundPlaceholder}, - {NTCID::kColorId_TextfieldDefaultColor, kColorTextfieldForeground}, - {NTCID::kColorId_TextfieldSelectionBackgroundFocused, - kColorTextfieldSelectionBackground}, - {NTCID::kColorId_TextfieldSelectionColor, - kColorTextfieldSelectionForeground}, - {NTCID::kColorId_ThrobberSpinningColor, kColorThrobber}, - {NTCID::kColorId_TooltipBackground, kColorTooltipBackground}, - {NTCID::kColorId_TooltipText, kColorTooltipForeground}, - {NTCID::kColorId_TreeBackground, kColorTreeBackground}, - {NTCID::kColorId_TreeText, kColorTreeNodeForeground}, - {NTCID::kColorId_TreeSelectionBackgroundFocused, - kColorTreeNodeBackgroundSelectedFocused}, - {NTCID::kColorId_TreeSelectedText, - kColorTreeNodeForegroundSelectedFocused}, - {NTCID::kColorId_TreeSelectionBackgroundUnfocused, - kColorTreeNodeBackgroundSelectedUnfocused}, - {NTCID::kColorId_TreeSelectedTextUnfocused, - kColorTreeNodeForegroundSelectedUnfocused}, - {NTCID::kColorId_WindowBackground, kColorWindowBackground}, - }); - DCHECK(color_id); - auto* color_it = map.find(native_theme_color_id); - if (color_it != map.cend()) { - *color_id = color_it->second; - return true; - } - return false; -} -// clang-format on void ReportHistogramBooleanUsesColorProvider(bool uses_color_provider) { UMA_HISTOGRAM_BOOLEAN("NativeTheme.GetSystemColor.UsesColorProvider", @@ -184,27 +51,16 @@ bool NativeTheme::SystemDarkModeSupported() { SkColor NativeTheme::GetSystemColor(ColorId color_id, ColorScheme color_scheme) const { - SCOPED_UMA_HISTOGRAM_TIMER("NativeTheme.GetSystemColor"); - if (color_scheme == NativeTheme::ColorScheme::kDefault) - color_scheme = GetDefaultSystemColorScheme(); + return GetSystemColorCommon(color_id, color_scheme, true); +} - // TODO(http://crbug.com/1057754): Remove the below restrictions. - if (base::FeatureList::IsEnabled(features::kColorProviderRedirection) && - color_scheme != NativeTheme::ColorScheme::kPlatformHighContrast) { - auto color_mode = (color_scheme == NativeTheme::ColorScheme::kDark) - ? ColorProviderManager::ColorMode::kDark - : ColorProviderManager::ColorMode::kLight; - // TODO(http://crbug.com/1057754): Handle high contrast modes. - auto* color_provider = ColorProviderManager::Get().GetColorProviderFor( - color_mode, ColorProviderManager::ContrastMode::kNormal); - ui::ColorId provider_color_id; - if (NativeThemeColorIdToColorId(color_id, &provider_color_id)) { - ReportHistogramBooleanUsesColorProvider(true); - return color_provider->GetColor(provider_color_id); - } - } - ReportHistogramBooleanUsesColorProvider(false); - return GetAuraColor(color_id, this, color_scheme); +SkColor NativeTheme::GetUnprocessedSystemColor(ColorId color_id, + ColorScheme color_scheme) const { + auto color = GetSystemColorCommon(color_id, color_scheme, false); + DVLOG(2) << "GetUnprocessedSystemColor: " + << "NativeTheme::ColorId: " << NativeThemeColorIdName(color_id) + << " Color: " << SkColorName(color); + return color; } SkColor NativeTheme::GetSystemButtonPressedColor(SkColor base_color) const { @@ -229,37 +85,52 @@ void NativeTheme::RemoveObserver(NativeThemeObserver* observer) { native_theme_observers_.RemoveObserver(observer); } -void NativeTheme::NotifyObservers() { +void NativeTheme::NotifyOnNativeThemeUpdated() { + // This specific method is prone to being mistakenly called on the wrong + // sequence, because it is often invoked from a platform-specific event + // listener, and those events may be delivered on unexpected sequences. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (NativeThemeObserver& observer : native_theme_observers_) observer.OnNativeThemeUpdated(this); } +void NativeTheme::NotifyOnCaptionStyleUpdated() { + // This specific method is prone to being mistakenly called on the wrong + // sequence, because it is often invoked from a platform-specific event + // listener, and those events may be delivered on unexpected sequences. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + for (NativeThemeObserver& observer : native_theme_observers_) + observer.OnCaptionStyleUpdated(); +} + NativeTheme::NativeTheme(bool should_use_dark_colors) : should_use_dark_colors_(should_use_dark_colors || IsForcedDarkMode()), forced_colors_(IsForcedHighContrast()), preferred_color_scheme_(CalculatePreferredColorScheme()), - preferred_contrast_(CalculatePreferredContrast()) { -#if !defined(OS_ANDROID) - // TODO(http://crbug.com/1057754): Merge this into the ColorProviderManager. - static base::OnceClosure color_provider_manager_init = base::BindOnce([]() { - ColorProviderManager::Get().SetColorProviderInitializer(base::BindRepeating( - [](ColorProvider* provider, ColorProviderManager::ColorMode color_mode, - ColorProviderManager::ContrastMode contrast_mode) { - const bool is_dark_color_mode = - color_mode == ColorProviderManager::ColorMode::kDark; - ui::AddCoreDefaultColorMixer(provider, is_dark_color_mode); - ui::AddNativeCoreColorMixer(provider, is_dark_color_mode); - ui::AddUiColorMixer(provider); - ui::AddNativeUiColorMixer(provider, is_dark_color_mode); - })); - }); - if (!color_provider_manager_init.is_null()) - std::move(color_provider_manager_init).Run(); -#endif // !defined(OS_ANDROID) -} + preferred_contrast_(CalculatePreferredContrast()) {} NativeTheme::~NativeTheme() = default; +base::Optional NativeTheme::GetColorProviderColor( + ColorId color_id, + ColorScheme color_scheme) const { + if (base::FeatureList::IsEnabled(features::kColorProviderRedirection) && + AllowColorPipelineRedirection(color_scheme)) { + if (auto provider_color_id = NativeThemeColorIdToColorId(color_id)) { + auto* color_provider = ColorProviderManager::Get().GetColorProviderFor( + {(color_scheme == NativeTheme::ColorScheme::kDark) + ? ColorProviderManager::ColorMode::kDark + : ColorProviderManager::ColorMode::kLight, + (color_scheme == NativeTheme::ColorScheme::kPlatformHighContrast) + ? ColorProviderManager::ContrastMode::kHigh + : ColorProviderManager::ContrastMode::kNormal}); + ReportHistogramBooleanUsesColorProvider(true); + return color_provider->GetColor(provider_color_id.value()); + } + } + return base::nullopt; +} + bool NativeTheme::ShouldUseDarkColors() const { return should_use_dark_colors_; } @@ -316,6 +187,22 @@ NativeTheme::PreferredContrast NativeTheme::CalculatePreferredContrast() const { : PreferredContrast::kNoPreference; } +bool NativeTheme::AllowColorPipelineRedirection( + ColorScheme color_scheme) const { + // TODO(kerenzhu): Don't use UserHasContrastPreference(). + // ColorScheme should encode high contrast info but currently on mac it does + // not. ColorScheme should also allow combination of light/dark mode with high + // contrast. + return color_scheme != ColorScheme::kPlatformHighContrast && + !UserHasContrastPreference(); +} + +SkColor NativeTheme::GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { + return GetAuraColor(color_id, this, color_scheme); +} + base::Optional NativeTheme::GetSystemCaptionStyle() const { return CaptionStyle::FromSystemSettings(); } @@ -406,11 +293,25 @@ void NativeTheme::ColorSchemeNativeThemeObserver::OnNativeThemeUpdated( } if (notify_observers) - theme_to_update_->NotifyObservers(); + theme_to_update_->NotifyOnNativeThemeUpdated(); } NativeTheme::ColorScheme NativeTheme::GetDefaultSystemColorScheme() const { return ShouldUseDarkColors() ? ColorScheme::kDark : ColorScheme::kLight; } +SkColor NativeTheme::GetSystemColorCommon(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { + SCOPED_UMA_HISTOGRAM_TIMER("NativeTheme.GetSystemColor"); + if (color_scheme == NativeTheme::ColorScheme::kDefault) + color_scheme = GetDefaultSystemColorScheme(); + + if (auto color = GetColorProviderColor(color_id, color_scheme)) + return color.value(); + + ReportHistogramBooleanUsesColorProvider(false); + return GetSystemColorDeprecated(color_id, color_scheme, apply_processing); +} + } // namespace ui diff --git a/chromium/ui/native_theme/native_theme.h b/chromium/ui/native_theme/native_theme.h index 3577f9b8fa7..b4f22b9e718 100644 --- a/chromium/ui/native_theme/native_theme.h +++ b/chromium/ui/native_theme/native_theme.h @@ -10,6 +10,8 @@ #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" @@ -146,14 +148,6 @@ class NATIVE_THEME_EXPORT NativeTheme { // Win) }; - // This enum represents the available unique security chip color states. - enum class SecurityChipColorId { - DEFAULT, - SECURE, - SECURE_WITH_CERT, - DANGEROUS, - }; - // Each structure below holds extra information needed when painting a given // part. @@ -343,13 +337,13 @@ class NATIVE_THEME_EXPORT NativeTheme { float height) const; // Paint the part to the canvas. - virtual void Paint( - cc::PaintCanvas* canvas, - Part part, - State state, - const gfx::Rect& rect, - const ExtraParams& extra, - ColorScheme color_scheme = ColorScheme::kDefault) const = 0; + virtual void Paint(cc::PaintCanvas* canvas, + Part part, + State state, + const gfx::Rect& rect, + const ExtraParams& extra, + ColorScheme color_scheme = ColorScheme::kDefault, + const base::Optional& accent_color = 0) const = 0; // Paint part during state transition, used for overlay scrollbar state // transition animation. @@ -399,11 +393,16 @@ class NATIVE_THEME_EXPORT NativeTheme { kMaxValue = kWindowText, }; - // Return a color from the system theme. - virtual SkColor GetSystemColor( + // Returns a color from the system theme. + SkColor GetSystemColor( ColorId color_id, ColorScheme color_scheme = ColorScheme::kDefault) const; + // Returns an un-tinted or unprocessed color from the system theme before + // processing. + SkColor GetUnprocessedSystemColor(ColorId color_id, + ColorScheme color_scheme) const; + // Returns a shared instance of the native theme that should be used for web // rendering. Do not use it in a normal application context (i.e. browser). // The returned object should not be deleted by the caller. This function is @@ -426,7 +425,10 @@ class NATIVE_THEME_EXPORT NativeTheme { void RemoveObserver(NativeThemeObserver* observer); // Notify observers of native theme changes. - virtual void NotifyObservers(); + virtual void NotifyOnNativeThemeUpdated(); + + // Notify observers of caption style changes. + virtual void NotifyOnCaptionStyleUpdated(); // Returns whether the user has an explicit contrast preference, i.e. whether // we are in forced colors mode or PreferredContrast is set. @@ -499,6 +501,10 @@ class NATIVE_THEME_EXPORT NativeTheme { explicit NativeTheme(bool should_only_use_dark_colors); virtual ~NativeTheme(); + // Gets the color from the color provider if using a color provider is enable. + base::Optional GetColorProviderColor(ColorId color_id, + ColorScheme color_scheme) const; + // Whether high contrast is forced via command-line flag. bool IsForcedHighContrast() const; // Whether dark mode is forced via command-line flag. @@ -524,6 +530,14 @@ class NATIVE_THEME_EXPORT NativeTheme { // platform behaviors. virtual void ConfigureWebInstance() {} + // TODO(http://crbug.com/1057754): Remove this. + virtual bool AllowColorPipelineRedirection(ColorScheme color_scheme) const; + + // Returns a color from the system theme, pre-Color Pipeline. + virtual SkColor GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const; + // Allows one native theme to observe changes in another. For example, the // web native theme for Windows observes the corresponding ui native theme in // order to receive changes regarding the state of dark mode, forced colors @@ -547,6 +561,10 @@ class NATIVE_THEME_EXPORT NativeTheme { mutable std::map system_colors_; private: + SkColor GetSystemColorCommon(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const; + // Observers to notify when the native theme changes. base::ObserverList::Unchecked native_theme_observers_; @@ -555,6 +573,8 @@ class NATIVE_THEME_EXPORT NativeTheme { PreferredColorScheme preferred_color_scheme_ = PreferredColorScheme::kLight; PreferredContrast preferred_contrast_ = PreferredContrast::kNoPreference; + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(NativeTheme); }; diff --git a/chromium/ui/native_theme/native_theme_android.cc b/chromium/ui/native_theme/native_theme_android.cc index f1d7851b850..26a083d96d4 100644 --- a/chromium/ui/native_theme/native_theme_android.cc +++ b/chromium/ui/native_theme/native_theme_android.cc @@ -41,8 +41,10 @@ gfx::Size NativeThemeAndroid::GetPartSize(Part part, return NativeThemeBase::GetPartSize(part, state, extra); } -SkColor NativeThemeAndroid::GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const { +SkColor NativeThemeAndroid::GetSystemColorDeprecated( + ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { NOTIMPLEMENTED(); return SK_ColorBLACK; } diff --git a/chromium/ui/native_theme/native_theme_android.h b/chromium/ui/native_theme/native_theme_android.h index 7635f727fac..864bd90b939 100644 --- a/chromium/ui/native_theme/native_theme_android.h +++ b/chromium/ui/native_theme/native_theme_android.h @@ -18,8 +18,9 @@ class NativeThemeAndroid : public NativeThemeBase { gfx::Size GetPartSize(Part part, State state, const ExtraParams& extra) const override; - SkColor GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const override; + SkColor GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const override; protected: friend class NativeTheme; diff --git a/chromium/ui/native_theme/native_theme_aura.cc b/chromium/ui/native_theme/native_theme_aura.cc index ef8d9335ae6..b45dcab92ba 100644 --- a/chromium/ui/native_theme/native_theme_aura.cc +++ b/chromium/ui/native_theme/native_theme_aura.cc @@ -241,47 +241,33 @@ void NativeThemeAura::PaintScrollbarThumb(cc::PaintCanvas* canvas, TRACE_EVENT0("blink", "NativeThemeAura::PaintScrollbarThumb"); - SkAlpha thumb_alpha = SK_AlphaTRANSPARENT; gfx::Rect thumb_rect(rect); SkColor thumb_color; if (use_overlay_scrollbars_) { - // Indexed by ScrollbarOverlayColorTheme. - constexpr SkColor kOverlayScrollbarThumbColor[] = {SK_ColorBLACK, - SK_ColorWHITE}; - constexpr SkColor kOverlayScrollbarStrokeColor[] = {SK_ColorWHITE, - SK_ColorBLACK}; - - thumb_color = kOverlayScrollbarThumbColor[theme]; - - SkAlpha stroke_alpha = SK_AlphaTRANSPARENT; - switch (state) { - case NativeTheme::kDisabled: - thumb_alpha = SK_AlphaTRANSPARENT; - stroke_alpha = SK_AlphaTRANSPARENT; - break; - case NativeTheme::kHovered: - thumb_alpha = SK_AlphaOPAQUE * kOverlayScrollbarThumbHoverAlpha; - stroke_alpha = SK_AlphaOPAQUE * kOverlayScrollbarStrokeHoverAlpha; - break; - case NativeTheme::kNormal: - thumb_alpha = SK_AlphaOPAQUE * kOverlayScrollbarThumbNormalAlpha; - stroke_alpha = SK_AlphaOPAQUE * kOverlayScrollbarStrokeNormalAlpha; - break; - case NativeTheme::kPressed: - thumb_alpha = SK_AlphaOPAQUE * kOverlayScrollbarThumbHoverAlpha; - stroke_alpha = SK_AlphaOPAQUE * kOverlayScrollbarStrokeHoverAlpha; - break; - case NativeTheme::kNumStates: - NOTREACHED(); - break; + if (state == NativeTheme::kDisabled) + return; + + const bool hovered = state != kNormal; + if (color_scheme != ColorScheme::kPlatformHighContrast) { + // A light system theme uses a dark overlay scrollbar, and vice versa. + color_scheme = (theme == ScrollbarOverlayColorThemeLight) + ? ColorScheme::kDark + : ColorScheme::kLight; } + thumb_color = + GetSystemColor(hovered ? kColorId_OverlayScrollbarThumbHoveredFill + : kColorId_OverlayScrollbarThumbFill, + color_scheme); + SkColor stroke_color = + GetSystemColor(hovered ? kColorId_OverlayScrollbarThumbHoveredStroke + : kColorId_OverlayScrollbarThumbStroke, + color_scheme); // In overlay mode, draw a stroke (border). constexpr int kStrokeWidth = kOverlayScrollbarStrokeWidth; cc::PaintFlags flags; - flags.setColor( - SkColorSetA(kOverlayScrollbarStrokeColor[theme], stroke_alpha)); + flags.setColor(stroke_color); flags.setStyle(cc::PaintFlags::kStroke_Style); flags.setStrokeWidth(kStrokeWidth); @@ -303,9 +289,9 @@ void NativeThemeAura::PaintScrollbarThumb(cc::PaintCanvas* canvas, thumb_rect.Inset(fill_insets + edge_adjust_insets); } else { ControlColorId color_id = kScrollbarThumb; + SkAlpha thumb_alpha = SK_AlphaTRANSPARENT; switch (state) { case NativeTheme::kDisabled: - thumb_alpha = SK_AlphaTRANSPARENT; break; case NativeTheme::kHovered: color_id = kScrollbarThumbHovered; @@ -332,16 +318,15 @@ void NativeThemeAura::PaintScrollbarThumb(cc::PaintCanvas* canvas, else thumb_rect.Inset(extra_padding, kThumbPadding); - if (InForcedColorsMode() && features::IsForcedColorsEnabled()) { - thumb_alpha = 0xFF; - thumb_color = GetControlColor(color_id, color_scheme); - } else { - thumb_color = GetControlColor(kScrollbarThumb, color_scheme); - } + thumb_color = + (InForcedColorsMode() && features::IsForcedColorsEnabled()) + ? GetControlColor(color_id, color_scheme) + : SkColorSetA(GetControlColor(kScrollbarThumb, color_scheme), + thumb_alpha); } cc::PaintFlags flags; - flags.setColor(SkColorSetA(thumb_color, thumb_alpha)); + flags.setColor(thumb_color); canvas->drawIRect(gfx::RectToSkIRect(thumb_rect), flags); } diff --git a/chromium/ui/native_theme/native_theme_base.cc b/chromium/ui/native_theme/native_theme_base.cc index 28661db79e7..313206e211c 100644 --- a/chromium/ui/native_theme/native_theme_base.cc +++ b/chromium/ui/native_theme/native_theme_base.cc @@ -143,6 +143,21 @@ SkColor BrightenColor(const color_utils::HSL& hsl, SkAlpha alpha, return color_utils::HSLToSkColor(adjusted, alpha); } +// This returns a color scheme which provides enough contrast with the custom +// accent-color to make it easy to see. +// 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& accent_color, + const ui::NativeTheme::ColorScheme& color_scheme) { + if (!accent_color) + return color_scheme; + + return color_utils::GetRelativeLuminance(*accent_color) < 0.5 + ? ui::NativeTheme::ColorScheme::kLight + : ui::NativeTheme::ColorScheme::kDark; +} + } // namespace namespace ui { @@ -243,7 +258,8 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas, State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const { + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (rect.IsEmpty()) return; @@ -253,7 +269,8 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas, switch (part) { // Please keep these in the order of NativeTheme::Part. case kCheckbox: - PaintCheckbox(canvas, state, rect, extra.button, color_scheme); + PaintCheckbox(canvas, state, rect, extra.button, color_scheme, + accent_color); break; // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete. @@ -282,13 +299,14 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas, color_scheme); break; case kProgressBar: - PaintProgressBar(canvas, state, rect, extra.progress_bar, color_scheme); + PaintProgressBar(canvas, state, rect, extra.progress_bar, color_scheme, + accent_color); break; case kPushButton: PaintButton(canvas, state, rect, extra.button, color_scheme); break; case kRadio: - PaintRadio(canvas, state, rect, extra.button, color_scheme); + PaintRadio(canvas, state, rect, extra.button, color_scheme, accent_color); break; case kScrollbarDownArrow: case kScrollbarUpArrow: @@ -317,10 +335,12 @@ void NativeThemeBase::Paint(cc::PaintCanvas* canvas, PaintScrollbarCorner(canvas, state, rect, color_scheme); break; case kSliderTrack: - PaintSliderTrack(canvas, state, rect, extra.slider, color_scheme); + PaintSliderTrack(canvas, state, rect, extra.slider, color_scheme, + accent_color); break; case kSliderThumb: - PaintSliderThumb(canvas, state, rect, extra.slider, color_scheme); + PaintSliderThumb(canvas, state, rect, extra.slider, color_scheme, + accent_color); break; case kTabPanelBackground: NOTIMPLEMENTED(); @@ -596,16 +616,22 @@ void NativeThemeBase::PaintScrollbarCorner(cc::PaintCanvas* canvas, const gfx::Rect& rect, ColorScheme color_scheme) const {} -void NativeThemeBase::PaintCheckbox(cc::PaintCanvas* canvas, - State state, - const gfx::Rect& rect, - const ButtonExtraParams& button, - ColorScheme color_scheme) const { +void NativeThemeBase::PaintCheckbox( + cc::PaintCanvas* canvas, + State state, + const gfx::Rect& rect, + const ButtonExtraParams& button, + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (features::IsFormControlsRefreshEnabled()) { + color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme); + const float border_radius = GetBorderRadiusForPart(kCheckbox, rect.width(), rect.height()); - SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, true, - border_radius, color_scheme); + + SkRect skrect = + PaintCheckboxRadioCommon(canvas, state, rect, button, true, + border_radius, color_scheme, accent_color); if (!skrect.isEmpty()) { cc::PaintFlags flags; @@ -623,7 +649,11 @@ void NativeThemeBase::PaintCheckbox(cc::PaintCanvas* canvas, } else if (button.checked) { // Draw the accent background. flags.setStyle(cc::PaintFlags::kFill_Style); - flags.setColor(ControlsAccentColorForState(state, color_scheme)); + if (accent_color && state != kDisabled) { + flags.setColor(*accent_color); + } else { + flags.setColor(ControlsAccentColorForState(state, color_scheme)); + } canvas->drawRoundRect(skrect, border_radius, border_radius, flags); // Draw the checkmark. @@ -643,8 +673,9 @@ void NativeThemeBase::PaintCheckbox(cc::PaintCanvas* canvas, return; } - SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, true, - SkIntToScalar(2), color_scheme); + SkRect skrect = + PaintCheckboxRadioCommon(canvas, state, rect, button, true, + SkIntToScalar(2), color_scheme, accent_color); if (!skrect.isEmpty()) { // Draw the checkmark / dash. cc::PaintFlags flags; @@ -683,8 +714,11 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon( const ButtonExtraParams& button, bool is_checkbox, const SkScalar border_radius, - ColorScheme color_scheme) const { + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (features::IsFormControlsRefreshEnabled()) { + color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme); + SkRect skrect = gfx::RectToSkRect(rect); // Use the largest square that fits inside the provided rectangle. @@ -700,7 +734,11 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon( // or underflow. if (skrect.width() <= 2) { cc::PaintFlags flags; - flags.setColor(GetControlColor(kBorder, color_scheme)); + if (accent_color && state != kDisabled) { + flags.setColor(*accent_color); + } else { + flags.setColor(GetControlColor(kBorder, color_scheme)); + } flags.setStyle(cc::PaintFlags::kFill_Style); canvas->drawRect(skrect, flags); // Too small to draw anything more. @@ -729,10 +767,17 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon( // within the rectangle. const auto border_rect = skrect.makeInset(kBorderWidth / 2, kBorderWidth / 2); - SkColor border_color = - (button.checked && !button.indeterminate) - ? ControlsAccentColorForState(state, color_scheme) - : ControlsBorderColorForState(state, color_scheme); + + SkColor border_color; + if (button.checked && !button.indeterminate) { + if (accent_color && state != kDisabled) { + border_color = *accent_color; + } else { + border_color = ControlsAccentColorForState(state, color_scheme); + } + } else { + border_color = ControlsBorderColorForState(state, color_scheme); + } flags.setColor(border_color); flags.setStyle(cc::PaintFlags::kStroke_Style); flags.setStrokeWidth(kBorderWidth); @@ -831,24 +876,33 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon( return skrect; } -void NativeThemeBase::PaintRadio(cc::PaintCanvas* canvas, - State state, - const gfx::Rect& rect, - const ButtonExtraParams& button, - ColorScheme color_scheme) const { +void NativeThemeBase::PaintRadio( + cc::PaintCanvas* canvas, + State state, + const gfx::Rect& rect, + const ButtonExtraParams& button, + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (features::IsFormControlsRefreshEnabled()) { + color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme); + // Most of a radio button is the same as a checkbox, except the the rounded // square is a circle (i.e. border radius >= 100%). const float border_radius = GetBorderRadiusForPart(kRadio, rect.width(), rect.height()); - SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, false, - border_radius, color_scheme); + SkRect skrect = + PaintCheckboxRadioCommon(canvas, state, rect, button, false, + border_radius, color_scheme, accent_color); if (!skrect.isEmpty() && button.checked) { // Draw the dot. cc::PaintFlags flags; flags.setAntiAlias(true); flags.setStyle(cc::PaintFlags::kFill_Style); - flags.setColor(ControlsAccentColorForState(state, color_scheme)); + if (accent_color && state != kDisabled) { + flags.setColor(*accent_color); + } else { + flags.setColor(ControlsAccentColorForState(state, color_scheme)); + } skrect.inset(skrect.width() * 0.2, skrect.height() * 0.2); // Use drawRoundedRect instead of drawOval to be completely consistent @@ -863,7 +917,7 @@ void NativeThemeBase::PaintRadio(cc::PaintCanvas* canvas, const SkScalar radius = SkFloatToScalar( static_cast(std::max(rect.width(), rect.height())) / 2); SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, false, - radius, color_scheme); + radius, color_scheme, accent_color); if (!skrect.isEmpty() && button.checked) { // Draw the dot. cc::PaintFlags flags; @@ -1139,12 +1193,16 @@ void NativeThemeBase::PaintMenuSeparator( canvas->drawRect(gfx::RectToSkRect(*menu_separator.paint_rect), flags); } -void NativeThemeBase::PaintSliderTrack(cc::PaintCanvas* canvas, - State state, - const gfx::Rect& rect, - const SliderExtraParams& slider, - ColorScheme color_scheme) const { +void NativeThemeBase::PaintSliderTrack( + cc::PaintCanvas* canvas, + State state, + const gfx::Rect& rect, + const SliderExtraParams& slider, + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (features::IsFormControlsRefreshEnabled()) { + color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme); + // Paint the entire slider track. cc::PaintFlags flags; flags.setAntiAlias(true); @@ -1168,7 +1226,13 @@ void NativeThemeBase::PaintSliderTrack(cc::PaintCanvas* canvas, canvas->clipRRect(rounded_rect, SkClipOp::kIntersect, true); // Paint the value slider track. - flags.setColor(ControlsSliderColorForState(state, color_scheme)); + if (accent_color && state != kDisabled) { + // TODO(crbug.com/1092093): Decide what to do when state is kHovered or + // kPressed. + flags.setColor(*accent_color); + } else { + flags.setColor(ControlsSliderColorForState(state, color_scheme)); + } SkRect value_rect = AlignSliderTrack(rect, slider, true, track_height); canvas->drawRect(value_rect, flags); @@ -1202,12 +1266,16 @@ void NativeThemeBase::PaintSliderTrack(cc::PaintCanvas* canvas, canvas->drawRect(skrect, flags); } -void NativeThemeBase::PaintSliderThumb(cc::PaintCanvas* canvas, - State state, - const gfx::Rect& rect, - const SliderExtraParams& slider, - ColorScheme color_scheme) const { +void NativeThemeBase::PaintSliderThumb( + cc::PaintCanvas* canvas, + State state, + const gfx::Rect& rect, + const SliderExtraParams& slider, + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (features::IsFormControlsRefreshEnabled()) { + color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme); + const float radius = GetBorderRadiusForPart(kSliderThumb, rect.width(), rect.height()); SkRect thumb_rect = gfx::RectToSkRect(rect); @@ -1221,7 +1289,13 @@ void NativeThemeBase::PaintSliderThumb(cc::PaintCanvas* canvas, // Paint the background (is not visible behind the rounded corners). thumb_rect.inset(border_width / 2, border_width / 2); - flags.setColor(ControlsSliderColorForState(state, color_scheme)); + if (accent_color && state != kDisabled) { + // TODO(crbug.com/1092093): Decide what to do when state is kHovered or + // kPressed. + flags.setColor(*accent_color); + } else { + flags.setColor(ControlsSliderColorForState(state, color_scheme)); + } flags.setStyle(cc::PaintFlags::kFill_Style); canvas->drawRoundRect(thumb_rect, radius, radius, flags); return; @@ -1298,10 +1372,13 @@ void NativeThemeBase::PaintProgressBar( State state, const gfx::Rect& rect, const ProgressBarExtraParams& progress_bar, - ColorScheme color_scheme) const { + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (features::IsFormControlsRefreshEnabled()) { DCHECK(!rect.IsEmpty()); + color_scheme = ColorSchemeForAccentColor(accent_color, color_scheme); + // Paint the track. cc::PaintFlags flags; flags.setAntiAlias(true); @@ -1330,7 +1407,11 @@ void NativeThemeBase::PaintProgressBar( progress_bar.value_rect_height); SkRect value_rect = AlignSliderTrack(original_value_rect, slider, false, track_height); - flags.setColor(GetControlColor(kAccent, color_scheme)); + if (accent_color) { + flags.setColor(*accent_color); + } else { + flags.setColor(GetControlColor(kAccent, color_scheme)); + } if (progress_bar.determinate) { canvas->drawRect(value_rect, flags); } else { diff --git a/chromium/ui/native_theme/native_theme_base.h b/chromium/ui/native_theme/native_theme_base.h index bb16add6804..a29df63b8a4 100644 --- a/chromium/ui/native_theme/native_theme_base.h +++ b/chromium/ui/native_theme/native_theme_base.h @@ -35,7 +35,8 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const override; + ColorScheme color_scheme, + const base::Optional& accent_color) const override; bool SupportsNinePatch(Part part) const override; gfx::Size GetNinePatchCanvasSize(Part part) const override; @@ -125,13 +126,15 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { State state, const gfx::Rect& rect, const ButtonExtraParams& button, - ColorScheme color_scheme) const; + ColorScheme color_scheme, + const base::Optional& accent_color) const; void PaintRadio(cc::PaintCanvas* canvas, State state, const gfx::Rect& rect, const ButtonExtraParams& button, - ColorScheme color_scheme) const; + ColorScheme color_scheme, + const base::Optional& accent_color) const; void PaintButton(cc::PaintCanvas* canvas, State state, @@ -174,13 +177,15 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { State state, const gfx::Rect& rect, const SliderExtraParams& slider, - ColorScheme color_scheme) const; + ColorScheme color_scheme, + const base::Optional& accent_color) const; void PaintSliderThumb(cc::PaintCanvas* canvas, State state, const gfx::Rect& rect, const SliderExtraParams& slider, - ColorScheme color_scheme) const; + ColorScheme color_scheme, + const base::Optional& accent_color) const; virtual void PaintInnerSpinButton( cc::PaintCanvas* canvas, @@ -193,7 +198,8 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { State state, const gfx::Rect& rect, const ProgressBarExtraParams& progress_bar, - ColorScheme color_scheme) const; + ColorScheme color_scheme, + const base::Optional& accent_color) const; virtual void PaintFrameTopArea(cc::PaintCanvas* canvas, State state, @@ -274,13 +280,15 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { // Paint the common parts of the checkboxes and radio buttons. // border_radius specifies how rounded the corners should be. - SkRect PaintCheckboxRadioCommon(cc::PaintCanvas* canvas, - State state, - const gfx::Rect& rect, - const ButtonExtraParams& button, - bool is_checkbox, - const SkScalar border_radius, - ColorScheme color_scheme) const; + SkRect PaintCheckboxRadioCommon( + cc::PaintCanvas* canvas, + State state, + const gfx::Rect& rect, + const ButtonExtraParams& button, + bool is_checkbox, + const SkScalar border_radius, + ColorScheme color_scheme, + const base::Optional& 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 d08b6a27c03..60197576c71 100644 --- a/chromium/ui/native_theme/native_theme_color_id.h +++ b/chromium/ui/native_theme/native_theme_color_id.h @@ -32,19 +32,14 @@ OP(kColorId_ButtonUncheckedColor), \ OP(kColorId_ButtonEnabledColor), \ OP(kColorId_ButtonDisabledColor), \ - OP(kColorId_ButtonHoverColor), \ - OP(kColorId_ButtonInkDropFillColor), \ - OP(kColorId_ButtonInkDropShadowColor), \ OP(kColorId_ProminentButtonColor), \ OP(kColorId_ProminentButtonDisabledColor), \ OP(kColorId_ProminentButtonFocusedColor), \ - OP(kColorId_ProminentButtonHoverColor), \ - OP(kColorId_ProminentButtonInkDropShadowColor), \ - OP(kColorId_ProminentButtonInkDropFillColor), \ OP(kColorId_TextOnProminentButtonColor), \ - OP(kColorId_PaddedButtonInkDropColor), \ /* ToggleButton */ \ OP(kColorId_ToggleButtonShadowColor), \ + OP(kColorId_ToggleButtonThumbColorOff), \ + OP(kColorId_ToggleButtonThumbColorOn), \ OP(kColorId_ToggleButtonTrackColorOff), \ OP(kColorId_ToggleButtonTrackColorOn), \ /* MenuItem */ \ @@ -88,16 +83,21 @@ OP(kColorId_LinkDisabled), \ OP(kColorId_LinkEnabled), \ OP(kColorId_LinkPressed), \ - OP(kColorId_OverlayScrollbarThumbBackground), \ - OP(kColorId_OverlayScrollbarThumbForeground), \ + /* Overlay scrollbar */ \ + OP(kColorId_OverlayScrollbarThumbFill), \ + OP(kColorId_OverlayScrollbarThumbHoveredFill), \ + OP(kColorId_OverlayScrollbarThumbHoveredStroke), \ + OP(kColorId_OverlayScrollbarThumbStroke), \ + /* Message Center */ \ + OP(kColorId_MessageCenterSmallImageMaskBackground), \ + OP(kColorId_MessageCenterSmallImageMaskForeground), \ /* Notification view */ \ - OP(kColorId_NotificationDefaultBackground), \ + OP(kColorId_NotificationBackground), \ + OP(kColorId_NotificationBackgroundActive), \ OP(kColorId_NotificationActionsRowBackground), \ - OP(kColorId_NotificationInlineSettingsBackground), \ OP(kColorId_NotificationLargeImageBackground), \ - OP(kColorId_NotificationPlaceholderIconColor), \ - OP(kColorId_NotificationEmptyPlaceholderIconColor), \ - OP(kColorId_NotificationEmptyPlaceholderTextColor), \ + OP(kColorId_NotificationColor), \ + OP(kColorId_NotificationPlaceholderColor), \ OP(kColorId_NotificationDefaultAccentColor), \ OP(kColorId_NotificationInkDropBase), \ /* Slider */ \ @@ -154,7 +154,6 @@ /* Colors for the material spinner (aka throbber). */ \ OP(kColorId_ThrobberSpinningColor), \ OP(kColorId_ThrobberWaitingColor), \ - OP(kColorId_ThrobberLightColor), \ /* Colors for Bubble Border */ \ OP(kColorId_BubbleBorder), \ /* Colors for Footnote Container. */ \ diff --git a/chromium/ui/native_theme/native_theme_mac.h b/chromium/ui/native_theme/native_theme_mac.h index 8961b9e9dfc..f83104b1d47 100644 --- a/chromium/ui/native_theme/native_theme_mac.h +++ b/chromium/ui/native_theme/native_theme_mac.h @@ -37,23 +37,21 @@ class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase { // an appropriate gray. static SkColor ApplySystemControlTint(SkColor color); - // Overridden from NativeTheme: - SkColor GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const override; - - // Overridden from NativeTheme: + // NativeTheme: + SkColor GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const override; SkColor GetSystemButtonPressedColor(SkColor base_color) const override; - - // Overridden from NativeTheme: PreferredContrast CalculatePreferredContrast() const override; - // Overridden from NativeThemeBase: + // NativeThemeBase: void Paint(cc::PaintCanvas* canvas, Part part, State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const override; + ColorScheme color_scheme, + const base::Optional& accent_color) const override; void PaintMenuPopupBackground( cc::PaintCanvas* canvas, const gfx::Size& size, diff --git a/chromium/ui/native_theme/native_theme_mac.mm b/chromium/ui/native_theme/native_theme_mac.mm index 59727173741..3eea09d9980 100644 --- a/chromium/ui/native_theme/native_theme_mac.mm +++ b/chromium/ui/native_theme/native_theme_mac.mm @@ -5,6 +5,7 @@ #include "ui/native_theme/native_theme_mac.h" #import +#include #include #include @@ -16,6 +17,7 @@ #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/color/mac/scoped_current_nsappearance.h" +#include "ui/color/mac/system_color_utils.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" @@ -101,17 +103,6 @@ struct EnumArray { VALUE array[static_cast(KEY::COUNT)]; }; -// Converts an SkColor to grayscale by using luminance for all three components. -// Experimentally, this seems to produce a better result than a flat average or -// a min/max average for UI controls. -SkColor ColorToGrayscale(SkColor color) { - SkScalar luminance = SkColorGetR(color) * 0.21 + - SkColorGetG(color) * 0.72 + - SkColorGetB(color) * 0.07; - uint8_t component = SkScalarRoundToInt(luminance); - return SkColorSetARGB(SkColorGetA(color), component, component, component); -} - } // namespace namespace ui { @@ -149,29 +140,13 @@ NativeThemeMac* NativeThemeMac::instance() { // static SkColor NativeThemeMac::ApplySystemControlTint(SkColor color) { - if ([NSColor currentControlTint] == NSGraphiteControlTint) - return ColorToGrayscale(color); - return color; -} - -SkColor NativeThemeMac::GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const { - if (color_scheme == ColorScheme::kDefault) - color_scheme = GetDefaultSystemColorScheme(); - - // The first check makes sure that when we are using the color providers that - // we actually go to the providers instead of just returning the colors - // below. The second check is to make sure that when not using color - // providers, we only skip the rest of the method when we are in an incognito - // window. - // TODO(http://crbug.com/1057754): Remove the && kPlatformHighContrast - // once NativeTheme.cc handles kColorProviderReirection and - // kPlatformHighContrast both being on. - if ((base::FeatureList::IsEnabled(features::kColorProviderRedirection) && - color_scheme != ColorScheme::kPlatformHighContrast)) - return NativeTheme::GetSystemColor(color_id, color_scheme); - - if (UserHasContrastPreference()) { + return ui::IsSystemGraphiteTinted() ? ui::ColorToGrayscale(color) : color; +} + +SkColor NativeThemeMac::GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { + if (GetPreferredContrast() == PreferredContrast::kMore) { switch (color_id) { case kColorId_SelectedMenuItemForegroundColor: return color_scheme == ColorScheme::kDark ? SK_ColorBLACK @@ -188,20 +163,24 @@ SkColor NativeThemeMac::GetSystemColor(ColorId color_id, if (os_color.has_value()) return os_color.value(); - return ApplySystemControlTint( - NativeTheme::GetSystemColor(color_id, color_scheme)); + SkColor color = NativeTheme::GetSystemColorDeprecated(color_id, color_scheme, + apply_processing); + return apply_processing ? ApplySystemControlTint(color) : color; } base::Optional NativeThemeMac::GetOSColor( ColorId color_id, ColorScheme color_scheme) const { - ScopedCurrentNSAppearance scoped_nsappearance(color_scheme == - ColorScheme::kDark); + ScopedCurrentNSAppearance scoped_nsappearance( + color_scheme == ColorScheme::kDark, + GetPreferredContrast() == PreferredContrast::kMore); // Even with --secondary-ui-md, menus use the platform colors and styling, and // Mac has a couple of specific color overrides, documented below. switch (color_id) { case kColorId_EnabledMenuItemForegroundColor: + case kColorId_HighlightedMenuItemForegroundColor: + case kColorId_SelectedMenuItemForegroundColor: return skia::NSSystemColorToSkColor([NSColor controlTextColor]); case kColorId_DisabledMenuItemForegroundColor: return skia::NSSystemColorToSkColor([NSColor disabledControlTextColor]); @@ -222,6 +201,7 @@ base::Optional NativeThemeMac::GetOSColor( [NSColor selectedTextBackgroundColor]); case kColorId_FocusedBorderColor: + case kColorId_TableGroupingIndicatorColor: return SkColorSetA( skia::NSSystemColorToSkColor([NSColor keyboardFocusIndicatorColor]), 0x66); @@ -250,7 +230,8 @@ void NativeThemeMac::Paint(cc::PaintCanvas* canvas, State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const { + ColorScheme color_scheme, + const base::Optional& accent_color) const { ColorScheme color_scheme_updated = color_scheme; if (color_scheme_updated == ColorScheme::kDefault) color_scheme_updated = GetDefaultSystemColorScheme(); @@ -274,7 +255,8 @@ void NativeThemeMac::Paint(cc::PaintCanvas* canvas, rect, color_scheme_updated, true); break; default: - NativeThemeBase::Paint(canvas, part, state, rect, extra, color_scheme); + NativeThemeBase::Paint(canvas, part, state, rect, extra, color_scheme, + accent_color); break; } } @@ -580,6 +562,15 @@ void NativeThemeMac::PaintMenuItemBackground( } } +// static +static void CaptionSettingsChangedNotificationCallback(CFNotificationCenterRef, + void*, + CFStringRef, + const void*, + CFDictionaryRef) { + NativeTheme::GetInstanceForWeb()->NotifyOnCaptionStyleUpdated(); +} + NativeThemeMac::NativeThemeMac(bool configure_web_instance, bool should_only_use_dark_colors) : NativeThemeBase(should_only_use_dark_colors) { @@ -598,7 +589,7 @@ NativeThemeMac::NativeThemeMac(bool configure_web_instance, usingBlock:^(NSNotification* notification) { theme->set_preferred_contrast( CalculatePreferredContrast()); - theme->NotifyObservers(); + theme->NotifyOnNativeThemeUpdated(); }]; } @@ -629,7 +620,7 @@ void NativeThemeMac::InitializeDarkModeStateAndObserver() { [[NativeThemeEffectiveAppearanceObserver alloc] initWithHandler:^{ theme->set_use_dark_colors(IsDarkMode()); theme->set_preferred_color_scheme(CalculatePreferredColorScheme()); - theme->NotifyObservers(); + theme->NotifyOnNativeThemeUpdated(); }]); } @@ -650,6 +641,13 @@ void NativeThemeMac::ConfigureWebInstance() { std::make_unique( NativeTheme::GetInstanceForWeb()); AddObserver(color_scheme_observer_.get()); + + // Observe caption style changes. + CFNotificationCenterAddObserver( + CFNotificationCenterGetLocalCenter(), this, + CaptionSettingsChangedNotificationCallback, + kMACaptionAppearanceSettingsChangedNotification, 0, + CFNotificationSuspensionBehaviorDeliverImmediately); } } // namespace ui diff --git a/chromium/ui/native_theme/native_theme_observer.h b/chromium/ui/native_theme/native_theme_observer.h index d38d66368a3..0a5431a5202 100644 --- a/chromium/ui/native_theme/native_theme_observer.h +++ b/chromium/ui/native_theme/native_theme_observer.h @@ -18,6 +18,9 @@ class NATIVE_THEME_EXPORT NativeThemeObserver { // observers may handle changes to their associated native theme instances. virtual void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) = 0; + // Called when the caption style changes. + virtual void OnCaptionStyleUpdated() {} + protected: virtual ~NativeThemeObserver(); }; diff --git a/chromium/ui/native_theme/native_theme_unittest.cc b/chromium/ui/native_theme/native_theme_unittest.cc index 2a32fb405bb..66f0960026e 100644 --- a/chromium/ui/native_theme/native_theme_unittest.cc +++ b/chromium/ui/native_theme/native_theme_unittest.cc @@ -7,53 +7,45 @@ #include #include +#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" #include "ui/base/ui_base_features.h" #include "ui/native_theme/native_theme_color_id.h" +#include "ui/native_theme/test/color_utils.h" -namespace ui { +#if defined(OS_MAC) +#include "ui/color/mac/system_color_utils.h" +#endif namespace { -constexpr const char* kColorIdStringName[] = { -#define OP(enum_name) #enum_name - NATIVE_THEME_COLOR_IDS -#undef OP -}; - -struct PrintableSkColor { - bool operator==(const PrintableSkColor& other) const { - return color == other.color; - } +enum class ContrastMode { kNonHighContrast, kHighContrast }; - bool operator!=(const PrintableSkColor& other) const { - return !operator==(other); - } - - const SkColor color; -}; +} // namespace -std::ostream& operator<<(std::ostream& os, PrintableSkColor printable_color) { - SkColor color = printable_color.color; - return os << base::StringPrintf("SkColorARGB(0x%02x, 0x%02x, 0x%02x, 0x%02x)", - SkColorGetA(color), SkColorGetR(color), - SkColorGetG(color), SkColorGetB(color)); -} +namespace ui { +namespace { class NativeThemeRedirectedEquivalenceTest - : public testing::TestWithParam< - std::tuple> { + : public testing::TestWithParam> { public: NativeThemeRedirectedEquivalenceTest() = default; static std::string ParamInfoToString( ::testing::TestParamInfo> param_info) { auto param_tuple = param_info.param; - return ColorSchemeToString(std::get<0>(param_tuple)) + "_With_" + - ColorIdToString(std::get<1>(param_tuple)); + return ColorSchemeToString( + std::get(param_tuple)) + + ContrastModeToString(std::get(param_tuple)) + + "_With_" + + test::ColorIdToString(std::get(param_tuple)); } private: @@ -72,44 +64,85 @@ class NativeThemeRedirectedEquivalenceTest } } - static std::string ColorIdToString(NativeTheme::ColorId id) { - if (id >= NativeTheme::ColorId::kColorId_NumColors) { - NOTREACHED() << "Invalid color value " << id; - return "InvalidColorId"; + static std::string ContrastModeToString(ContrastMode contrast_mode) { + switch (contrast_mode) { + case ContrastMode::kNonHighContrast: + return ""; + case ContrastMode::kHighContrast: + return "HighContrast"; + default: + NOTREACHED(); + return "InvalidContrastMode"; } - return kColorIdStringName[id]; } }; -} // namespace - -TEST_P(NativeThemeRedirectedEquivalenceTest, NativeUiGetSystemColor) { - // Verifies that colors with and without the Color Provider are the same. +std::pair +GetOriginalAndRedirected(NativeTheme::ColorId color_id, + NativeTheme::ColorScheme color_scheme, + ContrastMode contrast_mode) { NativeTheme* native_theme = NativeTheme::GetInstanceForNativeUi(); - auto param_tuple = GetParam(); - auto color_scheme = std::get<0>(param_tuple); - auto color_id = std::get<1>(param_tuple); - PrintableSkColor original{ + if (contrast_mode == ContrastMode::kHighContrast) { +#if defined(OS_WIN) + color_scheme = NativeTheme::ColorScheme::kPlatformHighContrast; +#endif + native_theme->set_preferred_contrast(NativeTheme::PreferredContrast::kMore); + } + + test::PrintableSkColor original{ native_theme->GetSystemColor(color_id, color_scheme)}; base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(features::kColorProviderRedirection); - PrintableSkColor redirected{ + test::PrintableSkColor redirected{ native_theme->GetSystemColor(color_id, color_scheme)}; + native_theme->set_preferred_contrast( + NativeTheme::PreferredContrast::kNoPreference); + + return std::make_pair(original, redirected); +} + +} // namespace + +TEST_P(NativeThemeRedirectedEquivalenceTest, NativeUiGetSystemColor) { + auto param_tuple = GetParam(); + auto color_scheme = std::get(param_tuple); + auto contrast_mode = std::get(param_tuple); + auto color_id = std::get(param_tuple); + + // Verifies that colors with and without the Color Provider are the same. + auto pair = GetOriginalAndRedirected(color_id, color_scheme, contrast_mode); + auto original = pair.first; + auto redirected = pair.second; + EXPECT_EQ(original, redirected); +} + +#if defined(OS_MAC) +TEST_P(NativeThemeRedirectedEquivalenceTest, NativeUiGetSystemColorWithTint) { + auto param_tuple = GetParam(); + auto color_scheme = std::get(param_tuple); + auto contrast_mode = std::get(param_tuple); + auto color_id = std::get(param_tuple); + ScopedEnableGraphiteTint enable_graphite_tint; + // Verifies that colors with and without the Color Provider are the same. + auto pair = GetOriginalAndRedirected(color_id, color_scheme, contrast_mode); + auto original = pair.first; + auto redirected = pair.second; EXPECT_EQ(original, redirected); } +#endif #define OP(enum_name) NativeTheme::ColorId::enum_name INSTANTIATE_TEST_SUITE_P( , NativeThemeRedirectedEquivalenceTest, - ::testing::Combine( - ::testing::Values(NativeTheme::ColorScheme::kLight, - NativeTheme::ColorScheme::kDark, - NativeTheme::ColorScheme::kPlatformHighContrast), - ::testing::Values(NATIVE_THEME_COLOR_IDS)), + ::testing::Combine(::testing::Values(NativeTheme::ColorScheme::kLight, + NativeTheme::ColorScheme::kDark), + ::testing::Values(ContrastMode::kNonHighContrast, + ContrastMode::kHighContrast), + ::testing::Values(NATIVE_THEME_COLOR_IDS)), NativeThemeRedirectedEquivalenceTest::ParamInfoToString); #undef OP diff --git a/chromium/ui/native_theme/native_theme_utils.cc b/chromium/ui/native_theme/native_theme_utils.cc new file mode 100644 index 00000000000..26d28f5ece1 --- /dev/null +++ b/chromium/ui/native_theme/native_theme_utils.cc @@ -0,0 +1,241 @@ +// 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/native_theme/native_theme_utils.h" + +#include "base/containers/fixed_flat_map.h" +#include "ui/color/color_id.h" +#include "ui/native_theme/native_theme_color_id.h" + +namespace ui { + +base::StringPiece NativeThemeColorIdName(NativeTheme::ColorId color_id) { + static constexpr const auto color_id_names = + base::MakeFixedFlatMap({ +#define OP(enum_name) {NativeTheme::ColorId::enum_name, #enum_name} + NATIVE_THEME_COLOR_IDS +#undef OP + }); + auto* it = color_id_names.find(color_id); + DCHECK_NE(color_id_names.cend(), it); + return it->second; +} + +base::StringPiece NativeThemeColorSchemeName( + NativeTheme::ColorScheme color_scheme) { + switch (color_scheme) { + case NativeTheme::ColorScheme::kDefault: + return "kDefault"; + case NativeTheme::ColorScheme::kLight: + return "kLight"; + case NativeTheme::ColorScheme::kDark: + return "kDark"; + case NativeTheme::ColorScheme::kPlatformHighContrast: + return "kPlatformHighContrast"; + default: + NOTREACHED() << "Invalid NativeTheme::ColorScheme"; + return ""; + } +} + +// clang-format off +base::Optional +NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id) { + using NTCID = NativeTheme::ColorId; + static constexpr const auto map = + base::MakeFixedFlatMap({ + {NTCID::kColorId_AlertSeverityHigh, kColorAlertHighSeverity}, + {NTCID::kColorId_AlertSeverityLow, kColorAlertLowSeverity}, + {NTCID::kColorId_AlertSeverityMedium, kColorAlertMediumSeverity}, + {NTCID::kColorId_AvatarHeaderArt, kColorAvatarHeaderArt}, + {NTCID::kColorId_AvatarIconGuest, kColorAvatarIconGuest}, + {NTCID::kColorId_AvatarIconIncognito, kColorAvatarIconIncognito}, + {NTCID::kColorId_BubbleBackground, kColorBubbleBackground}, + {NTCID::kColorId_BubbleBorder, kColorBubbleBorder}, + {NTCID::kColorId_BubbleFooterBackground, + kColorBubbleFooterBackground}, + {NTCID::kColorId_ButtonBorderColor, kColorButtonBorder}, + {NTCID::kColorId_ButtonCheckedColor, kColorButtonForegroundChecked}, + {NTCID::kColorId_ButtonColor, kColorButtonBackground}, + {NTCID::kColorId_ButtonDisabledColor, + kColorButtonForegroundDisabled}, + {NTCID::kColorId_ButtonEnabledColor, kColorButtonForeground}, + {NTCID::kColorId_ButtonUncheckedColor, + kColorButtonForegroundUnchecked}, + {NTCID::kColorId_CustomFrameActiveColor, kColorFrameActive}, + {NTCID::kColorId_CustomFrameInactiveColor, kColorFrameInactive}, + {NTCID::kColorId_CustomTabBarBackgroundColor, + kColorPwaToolbarBackground}, + {NTCID::kColorId_CustomTabBarForegroundColor, + kColorPwaToolbarForeground}, + {NTCID::kColorId_CustomTabBarSecurityChipDangerousColor, + kColorPwaSecurityChipForegroundDangerous}, + {NTCID::kColorId_CustomTabBarSecurityChipDefaultColor, + kColorPwaSecurityChipForeground}, + {NTCID::kColorId_CustomTabBarSecurityChipSecureColor, + kColorPwaSecurityChipForegroundSecure}, + {NTCID::kColorId_CustomTabBarSecurityChipWithCertColor, + kColorPwaSecurityChipForegroundPolicyCert}, + {NTCID::kColorId_DefaultIconColor, kColorIcon}, + {NTCID::kColorId_DialogBackground, kColorDialogBackground}, + {NTCID::kColorId_DialogForeground, kColorDialogForeground}, + {NTCID::kColorId_DisabledButtonBorderColor, kColorButtonBorderDisabled}, + {NTCID::kColorId_DisabledIconColor, kColorIconDisabled}, + {NTCID::kColorId_DisabledMenuItemForegroundColor, + kColorMenuItemForegroundDisabled}, + {NTCID::kColorId_DropdownBackgroundColor, kColorDropdownBackground}, + {NTCID::kColorId_DropdownForegroundColor, kColorDropdownForeground}, + {NTCID::kColorId_DropdownSelectedBackgroundColor, + kColorDropdownBackgroundSelected}, + {NTCID::kColorId_DropdownSelectedForegroundColor, + kColorDropdownForegroundSelected}, + {NTCID::kColorId_EnabledMenuItemForegroundColor, + kColorMenuItemForeground}, + {NTCID::kColorId_FocusedBorderColor, kColorFocusableBorderFocused}, + {NTCID::kColorId_FocusedMenuItemBackgroundColor, + kColorMenuItemBackgroundSelected}, + {NTCID::kColorId_FootnoteContainerBorder, kColorBubbleFooterBorder}, + {NTCID::kColorId_HighlightedMenuItemBackgroundColor, + kColorMenuItemBackgroundHighlighted}, + {NTCID::kColorId_HighlightedMenuItemForegroundColor, + kColorMenuItemForegroundHighlighted}, + {NTCID::kColorId_LabelDisabledColor, kColorLabelForegroundDisabled}, + {NTCID::kColorId_LabelEnabledColor, kColorLabelForeground}, + {NTCID::kColorId_LabelSecondaryColor, + kColorLabelForegroundSecondary}, + {NTCID::kColorId_LabelTextSelectionBackgroundFocused, + kColorLabelSelectionBackground}, + {NTCID::kColorId_LabelTextSelectionColor, + kColorLabelSelectionForeground}, + {NTCID::kColorId_LinkDisabled, kColorLinkForegroundDisabled}, + {NTCID::kColorId_LinkEnabled, kColorLinkForeground}, + {NTCID::kColorId_LinkPressed, kColorLinkForegroundPressed}, + {NTCID::kColorId_MenuBackgroundColor, kColorMenuBackground}, + {NTCID::kColorId_MenuBorderColor, kColorMenuBorder}, + {NTCID::kColorId_MenuDropIndicator, kColorMenuDropmarker}, + {NTCID::kColorId_MenuIconColor, kColorMenuIcon}, + {NTCID::kColorId_MenuItemInitialAlertBackgroundColor, + kColorMenuItemBackgroundAlertedInitial}, + {NTCID::kColorId_MenuItemMinorTextColor, + kColorMenuItemForegroundSecondary}, + {NTCID::kColorId_MenuItemTargetAlertBackgroundColor, + kColorMenuItemBackgroundAlertedTarget}, + {NTCID::kColorId_MenuSeparatorColor, kColorMenuSeparator}, + {NTCID::kColorId_MessageCenterSmallImageMaskBackground, + kColorNotificationIconBackground}, + {NTCID::kColorId_MessageCenterSmallImageMaskForeground, + kColorNotificationIconForeground}, + {NTCID::kColorId_NotificationActionsRowBackground, + kColorNotificationActionsBackground}, + {NTCID::kColorId_NotificationBackground, + kColorNotificationBackgroundInactive}, + {NTCID::kColorId_NotificationBackgroundActive, + kColorNotificationBackgroundActive}, + {NTCID::kColorId_NotificationColor, kColorNotificationInputForeground}, + {NTCID::kColorId_NotificationDefaultAccentColor, + kColorNotificationHeaderForeground}, + {NTCID::kColorId_NotificationInkDropBase, + kColorNotificationInputBackground}, + {NTCID::kColorId_NotificationLargeImageBackground, + kColorNotificationImageBackground}, + {NTCID::kColorId_NotificationPlaceholderColor, + kColorNotificationInputPlaceholderForeground}, + {NTCID::kColorId_OverlayScrollbarThumbFill, kColorOverlayScrollbarFill}, + {NTCID::kColorId_OverlayScrollbarThumbHoveredFill, + kColorOverlayScrollbarFillHovered}, + {NTCID::kColorId_OverlayScrollbarThumbHoveredStroke, + kColorOverlayScrollbarStrokeHovered}, + {NTCID::kColorId_OverlayScrollbarThumbStroke, + kColorOverlayScrollbarStroke}, + {NTCID::kColorId_ProminentButtonColor, + kColorButtonBackgroundProminent}, + {NTCID::kColorId_ProminentButtonDisabledColor, + kColorButtonBackgroundProminentDisabled}, + {NTCID::kColorId_ProminentButtonFocusedColor, + kColorButtonBackgroundProminentFocused}, + {NTCID::kColorId_SelectedMenuItemForegroundColor, + kColorMenuItemForegroundSelected}, + {NTCID::kColorId_SeparatorColor, kColorSeparator}, + {NTCID::kColorId_SliderThumbDefault, kColorSliderThumb}, + {NTCID::kColorId_SliderThumbMinimal, kColorSliderThumbMinimal}, + {NTCID::kColorId_SliderTroughDefault, kColorSliderTrack}, + {NTCID::kColorId_SliderTroughMinimal, kColorSliderTrackMinimal}, + {NTCID::kColorId_SyncInfoContainerError, kColorSyncInfoBackgroundError}, + {NTCID::kColorId_SyncInfoContainerNoPrimaryAccount, + kColorSyncInfoBackground}, + {NTCID::kColorId_SyncInfoContainerPaused, + kColorSyncInfoBackgroundPaused}, + {NTCID::kColorId_TabBottomBorder, kColorTabContentSeparator}, + {NTCID::kColorId_TabHighlightBackground, + kColorTabBackgroundHighlighted}, + {NTCID::kColorId_TabHighlightFocusedBackground, + kColorTabBackgroundHighlightedFocused}, + {NTCID::kColorId_TableBackground, kColorTableBackground}, + {NTCID::kColorId_TableBackgroundAlternate, + kColorTableBackgroundAlternate}, + {NTCID::kColorId_TableGroupingIndicatorColor, + kColorTableGroupingIndicator}, + {NTCID::kColorId_TableHeaderBackground, kColorTableHeaderBackground}, + {NTCID::kColorId_TableHeaderSeparator, kColorTableHeaderSeparator}, + {NTCID::kColorId_TableHeaderText, kColorTableHeaderForeground}, + {NTCID::kColorId_TableSelectedText, + kColorTableForegroundSelectedFocused}, + {NTCID::kColorId_TableSelectedTextUnfocused, + kColorTableForegroundSelectedUnfocused}, + {NTCID::kColorId_TableSelectionBackgroundFocused, + kColorTableBackgroundSelectedFocused}, + {NTCID::kColorId_TableSelectionBackgroundUnfocused, + kColorTableBackgroundSelectedUnfocused}, + {NTCID::kColorId_TableText, kColorTableForeground}, + {NTCID::kColorId_TabSelectedBorderColor, kColorTabBorderSelected}, + {NTCID::kColorId_TabTitleColorActive, kColorTabForegroundSelected}, + {NTCID::kColorId_TabTitleColorInactive, kColorTabForeground}, + {NTCID::kColorId_TextfieldDefaultBackground, + kColorTextfieldBackground}, + {NTCID::kColorId_TextfieldDefaultColor, kColorTextfieldForeground}, + {NTCID::kColorId_TextfieldPlaceholderColor, + kColorTextfieldForegroundPlaceholder}, + {NTCID::kColorId_TextfieldReadOnlyBackground, + kColorTextfieldBackgroundDisabled}, + {NTCID::kColorId_TextfieldReadOnlyColor, + kColorTextfieldForegroundDisabled}, + {NTCID::kColorId_TextfieldSelectionBackgroundFocused, + kColorTextfieldSelectionBackground}, + {NTCID::kColorId_TextfieldSelectionColor, + kColorTextfieldSelectionForeground}, + {NTCID::kColorId_TextOnProminentButtonColor, + kColorButtonForegroundProminent}, + {NTCID::kColorId_ThrobberSpinningColor, kColorThrobber}, + {NTCID::kColorId_ThrobberWaitingColor, kColorThrobberPreconnect}, + {NTCID::kColorId_ToggleButtonShadowColor, kColorToggleButtonShadow}, + {NTCID::kColorId_ToggleButtonThumbColorOff, kColorToggleButtonThumbOff}, + {NTCID::kColorId_ToggleButtonThumbColorOn, kColorToggleButtonThumbOn}, + {NTCID::kColorId_ToggleButtonTrackColorOff, kColorToggleButtonTrackOff}, + {NTCID::kColorId_ToggleButtonTrackColorOn, kColorToggleButtonTrackOn}, + {NTCID::kColorId_TooltipBackground, kColorTooltipBackground}, + {NTCID::kColorId_TooltipIcon, kColorHelpIconInactive}, + {NTCID::kColorId_TooltipIconHovered, kColorHelpIconActive}, + {NTCID::kColorId_TooltipText, kColorTooltipForeground}, + {NTCID::kColorId_TreeBackground, kColorTreeBackground}, + {NTCID::kColorId_TreeSelectedText, + kColorTreeNodeForegroundSelectedFocused}, + {NTCID::kColorId_TreeSelectedTextUnfocused, + kColorTreeNodeForegroundSelectedUnfocused}, + {NTCID::kColorId_TreeSelectionBackgroundFocused, + kColorTreeNodeBackgroundSelectedFocused}, + {NTCID::kColorId_TreeSelectionBackgroundUnfocused, + kColorTreeNodeBackgroundSelectedUnfocused}, + {NTCID::kColorId_TreeText, kColorTreeNodeForeground}, + {NTCID::kColorId_UnfocusedBorderColor, kColorFocusableBorderUnfocused}, + {NTCID::kColorId_WindowBackground, kColorWindowBackground}, + }); + auto* color_it = map.find(native_theme_color_id); + if (color_it != map.cend()) { + return color_it->second; + } + return base::nullopt; +} +// clang-format on + +} // namespace ui diff --git a/chromium/ui/native_theme/native_theme_utils.h b/chromium/ui/native_theme/native_theme_utils.h new file mode 100644 index 00000000000..39a00a766fa --- /dev/null +++ b/chromium/ui/native_theme/native_theme_utils.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_NATIVE_THEME_NATIVE_THEME_UTILS_H_ +#define UI_NATIVE_THEME_NATIVE_THEME_UTILS_H_ + +#include "base/strings/string_piece.h" +#include "ui/color/color_id.h" +#include "ui/native_theme/native_theme.h" +#include "ui/native_theme/native_theme_export.h" + +namespace ui { + +// The following functions convert various values to strings intended for +// logging. Do not retain the results for longer than the scope in which these +// functions are called. + +// Converts NativeTheme::ColorId. +base::StringPiece NATIVE_THEME_EXPORT +NativeThemeColorIdName(NativeTheme::ColorId color_id); + +// Converts NativeTheme::ColorScheme. +base::StringPiece NATIVE_THEME_EXPORT +NativeThemeColorSchemeName(NativeTheme::ColorScheme color_scheme); + +// Converts a NativeTheme::ColorId to a ColorPipeline ColorId. +base::Optional NATIVE_THEME_EXPORT +NativeThemeColorIdToColorId(NativeTheme::ColorId native_theme_color_id); + +} // namespace ui + +#endif // UI_NATIVE_THEME_NATIVE_THEME_UTILS_H_ diff --git a/chromium/ui/native_theme/native_theme_win.cc b/chromium/ui/native_theme/native_theme_win.cc index 4d0ed521015..68b798fc755 100644 --- a/chromium/ui/native_theme/native_theme_win.cc +++ b/chromium/ui/native_theme/native_theme_win.cc @@ -14,6 +14,7 @@ #include "base/callback.h" #include "base/check.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/notreached.h" #include "base/optional.h" #include "base/stl_util.h" @@ -247,7 +248,8 @@ void NativeThemeWin::Paint(cc::PaintCanvas* canvas, State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const { + ColorScheme color_scheme, + const base::Optional& accent_color) const { if (rect.IsEmpty()) return; @@ -322,6 +324,23 @@ void NativeThemeWin::ConfigureWebInstance() { web_instance->set_system_colors(GetSystemColors()); } +bool NativeThemeWin::AllowColorPipelineRedirection( + ColorScheme color_scheme) const { + return true; +} + +SkColor NativeThemeWin::GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { + base::Optional color; + if (color_scheme == ColorScheme::kPlatformHighContrast && + (color = GetPlatformHighContrastColor(color_id))) { + return color.value(); + } + return NativeTheme::GetSystemColorDeprecated(color_id, color_scheme, + apply_processing); +} + NativeThemeWin::~NativeThemeWin() { // TODO(https://crbug.com/787692): Calling CloseHandles() here breaks // certain tests and the reliability bots. @@ -350,7 +369,7 @@ void NativeThemeWin::OnSysColorChange() { set_forced_colors(IsUsingHighContrastThemeInternal()); set_preferred_color_scheme(CalculatePreferredColorScheme()); set_preferred_contrast(CalculatePreferredContrast()); - NotifyObservers(); + NotifyOnNativeThemeUpdated(); } void NativeThemeWin::UpdateSystemColors() { @@ -590,17 +609,6 @@ void NativeThemeWin::PaintDirect(SkCanvas* destination_canvas, } } -SkColor NativeThemeWin::GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const { - if (color_scheme == ColorScheme::kDefault) - color_scheme = GetDefaultSystemColorScheme(); - - base::Optional color; - if (color_scheme == ColorScheme::kPlatformHighContrast) - color = GetPlatformHighContrastColor(color_id); - return color.value_or(NativeTheme::GetSystemColor(color_id, color_scheme)); -} - base::Optional NativeThemeWin::GetPlatformHighContrastColor( ColorId color_id) const { switch (color_id) { @@ -615,7 +623,7 @@ base::Optional NativeThemeWin::GetPlatformHighContrastColor( case kColorId_TableBackgroundAlternate: case kColorId_TooltipBackground: case kColorId_ProminentButtonDisabledColor: - case kColorId_NotificationDefaultBackground: + case kColorId_NotificationBackground: return system_colors_[SystemThemeColor::kWindow]; // Window Text @@ -631,7 +639,6 @@ base::Optional NativeThemeWin::GetPlatformHighContrastColor( case kColorId_TooltipIcon: case kColorId_TooltipText: case kColorId_ThrobberSpinningColor: - case kColorId_ThrobberLightColor: case kColorId_AlertSeverityLow: case kColorId_AlertSeverityMedium: case kColorId_AlertSeverityHigh: @@ -681,6 +688,7 @@ base::Optional NativeThemeWin::GetPlatformHighContrastColor( case kColorId_ProminentButtonColor: case kColorId_ProminentButtonFocusedColor: case kColorId_ButtonBorderColor: + case kColorId_DropdownSelectedBackgroundColor: case kColorId_FocusedMenuItemBackgroundColor: case kColorId_LabelTextSelectionBackgroundFocused: case kColorId_TextfieldSelectionBackgroundFocused: @@ -1683,7 +1691,7 @@ void NativeThemeWin::UpdateDarkModeStatus() { } set_use_dark_colors(dark_mode_enabled); set_preferred_color_scheme(CalculatePreferredColorScheme()); - NotifyObservers(); + NotifyOnNativeThemeUpdated(); } } // namespace ui diff --git a/chromium/ui/native_theme/native_theme_win.h b/chromium/ui/native_theme/native_theme_win.h index 236565d507d..8b273714d3d 100644 --- a/chromium/ui/native_theme/native_theme_win.h +++ b/chromium/ui/native_theme/native_theme_win.h @@ -64,10 +64,8 @@ class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme, State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const override; - SkColor GetSystemColor( - ColorId color_id, - ColorScheme color_scheme = ColorScheme::kDefault) const override; + ColorScheme color_scheme, + const base::Optional& accent_color) const override; bool SupportsNinePatch(Part part) const override; gfx::Size GetNinePatchCanvasSize(Part part) const override; gfx::Rect GetNinePatchAperture(Part part) const override; @@ -80,7 +78,12 @@ class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme, friend class NativeTheme; friend class base::NoDestructor; + // NativeTheme: void ConfigureWebInstance() override; + bool AllowColorPipelineRedirection(ColorScheme color_scheme) const override; + SkColor GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const override; NativeThemeWin(bool configure_web_instance, bool should_only_use_dark_colors); ~NativeThemeWin() override; @@ -89,7 +92,7 @@ class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme, bool IsUsingHighContrastThemeInternal() const; void CloseHandlesInternal(); - // gfx::SysColorChangeListener implementation: + // gfx::SysColorChangeListener: void OnSysColorChange() override; // Update the locally cached set of system colors. diff --git a/chromium/ui/native_theme/overlay_scrollbar_constants_aura.h b/chromium/ui/native_theme/overlay_scrollbar_constants_aura.h index 9ecba8aaa33..b9408b5c067 100644 --- a/chromium/ui/native_theme/overlay_scrollbar_constants_aura.h +++ b/chromium/ui/native_theme/overlay_scrollbar_constants_aura.h @@ -13,11 +13,6 @@ namespace ui { constexpr int kOverlayScrollbarStrokeWidth = 1; constexpr int kOverlayScrollbarThumbWidthPressed = 10; -constexpr float kOverlayScrollbarThumbNormalAlpha = 0.5f; -constexpr float kOverlayScrollbarThumbHoverAlpha = 0.7f; -constexpr float kOverlayScrollbarStrokeNormalAlpha = 0.3f; -constexpr float kOverlayScrollbarStrokeHoverAlpha = 0.5f; - constexpr base::TimeDelta kOverlayScrollbarFadeDelay = base::TimeDelta::FromMilliseconds(500); constexpr base::TimeDelta kOverlayScrollbarFadeDuration = diff --git a/chromium/ui/native_theme/test_native_theme.cc b/chromium/ui/native_theme/test_native_theme.cc index 3abb74e3ca9..f6413f2971b 100644 --- a/chromium/ui/native_theme/test_native_theme.cc +++ b/chromium/ui/native_theme/test_native_theme.cc @@ -9,11 +9,6 @@ namespace ui { TestNativeTheme::TestNativeTheme() : NativeTheme(false) {} TestNativeTheme::~TestNativeTheme() = default; -SkColor TestNativeTheme::GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const { - return SK_ColorRED; -} - gfx::Size TestNativeTheme::GetPartSize(Part part, State state, const ExtraParams& extra) const { @@ -25,7 +20,9 @@ void TestNativeTheme::Paint(cc::PaintCanvas* canvas, State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const {} + ColorScheme color_scheme, + const base::Optional& accent_color) const { +} bool TestNativeTheme::SupportsNinePatch(Part part) const { return false; @@ -66,4 +63,10 @@ void TestNativeTheme::AddColorSchemeNativeThemeObserver( AddObserver(color_scheme_observer_.get()); } +SkColor TestNativeTheme::GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const { + return SK_ColorRED; +} + } // namespace ui diff --git a/chromium/ui/native_theme/test_native_theme.h b/chromium/ui/native_theme/test_native_theme.h index fb03c61aae8..f66cd329df1 100644 --- a/chromium/ui/native_theme/test_native_theme.h +++ b/chromium/ui/native_theme/test_native_theme.h @@ -16,8 +16,6 @@ class TestNativeTheme : public NativeTheme { ~TestNativeTheme() override; // NativeTheme: - SkColor GetSystemColor(ColorId color_id, - ColorScheme color_scheme) const override; gfx::Size GetPartSize(Part part, State state, const ExtraParams& extra) const override; @@ -26,7 +24,8 @@ class TestNativeTheme : public NativeTheme { State state, const gfx::Rect& rect, const ExtraParams& extra, - ColorScheme color_scheme) const override; + ColorScheme color_scheme, + const base::Optional& accent_color) const override; bool SupportsNinePatch(Part part) const override; gfx::Size GetNinePatchCanvasSize(Part part) const override; gfx::Rect GetNinePatchAperture(Part part) const override; @@ -44,6 +43,11 @@ class TestNativeTheme : public NativeTheme { } void AddColorSchemeNativeThemeObserver(NativeTheme* theme_to_update); + protected: + SkColor GetSystemColorDeprecated(ColorId color_id, + ColorScheme color_scheme, + bool apply_processing) const override; + private: bool dark_mode_ = false; bool contrast_preference_ = false; diff --git a/chromium/ui/ozone/BUILD.gn b/chromium/ui/ozone/BUILD.gn index e788273148e..d0dfdfba774 100644 --- a/chromium/ui/ozone/BUILD.gn +++ b/chromium/ui/ozone/BUILD.gn @@ -51,6 +51,7 @@ if (ozone_platform_wayland) { ozone_platforms += [ "wayland" ] ozone_platform_deps += [ "platform/wayland" ] ozone_platform_test_deps += [ "platform/wayland:wayland_unittests" ] + ozone_platform_ui_test_support_deps += [ "platform/wayland:ui_test_support" ] } if (ozone_platform_x11) { @@ -62,6 +63,7 @@ if (ozone_platform_x11) { if (ozone_platform_scenic) { ozone_platforms += [ "scenic" ] ozone_platform_deps += [ "platform/scenic" ] + ozone_platform_test_deps += [ "platform/scenic:scenic_unittests" ] } platform_list_cc_file = "$target_gen_dir/platform_list.cc" @@ -92,12 +94,15 @@ component("ozone_base") { "public/platform_clipboard.h", "public/platform_gl_egl_utility.cc", "public/platform_gl_egl_utility.h", + "public/platform_global_shortcut_listener.cc", + "public/platform_global_shortcut_listener.h", "public/platform_menu_utils.cc", "public/platform_menu_utils.h", "public/platform_screen.cc", "public/platform_screen.h", "public/platform_user_input_monitor.cc", "public/platform_user_input_monitor.h", + "public/platform_utils.h", "public/platform_window_surface.h", "public/surface_factory_ozone.cc", "public/surface_factory_ozone.h", diff --git a/chromium/ui/ozone/common/egl_util.cc b/chromium/ui/ozone/common/egl_util.cc index d23a6014601..9b322cd4ae7 100644 --- a/chromium/ui/ozone/common/egl_util.cc +++ b/chromium/ui/ozone/common/egl_util.cc @@ -147,11 +147,12 @@ bool LoadEGLGLES2Bindings(const base::FilePath& egl_library_path, } // namespace -bool LoadDefaultEGLGLES2Bindings(gl::GLImplementation implementation) { +bool LoadDefaultEGLGLES2Bindings( + const gl::GLImplementationParts& implementation) { base::FilePath glesv2_path; base::FilePath egl_path; - if (implementation == gl::kGLImplementationSwiftShaderGL) { + if (implementation.gl == gl::kGLImplementationSwiftShaderGL) { #if BUILDFLAG(ENABLE_SWIFTSHADER) base::FilePath module_path; #if !defined(OS_FUCHSIA) @@ -165,7 +166,7 @@ bool LoadDefaultEGLGLES2Bindings(gl::GLImplementation implementation) { #else return false; #endif - } else if (implementation == gl::kGLImplementationEGLANGLE) { + } else if (implementation.gl == gl::kGLImplementationEGLANGLE) { glesv2_path = base::FilePath(kAngleGlesSoname); egl_path = base::FilePath(kAngleEglSoname); } else { diff --git a/chromium/ui/ozone/common/egl_util.h b/chromium/ui/ozone/common/egl_util.h index 788083ff4eb..d7a95c77cde 100644 --- a/chromium/ui/ozone/common/egl_util.h +++ b/chromium/ui/ozone/common/egl_util.h @@ -11,7 +11,7 @@ namespace ui { -bool LoadDefaultEGLGLES2Bindings(gl::GLImplementation impl); +bool LoadDefaultEGLGLES2Bindings(const gl::GLImplementationParts& impl); void* /* EGLConfig */ ChooseEGLConfig(void* /* EGLConfig */ display, const int32_t* attributes); diff --git a/chromium/ui/ozone/common/gl_ozone_egl.cc b/chromium/ui/ozone/common/gl_ozone_egl.cc index 7c2758ca8b8..194d29f754d 100644 --- a/chromium/ui/ozone/common/gl_ozone_egl.cc +++ b/chromium/ui/ozone/common/gl_ozone_egl.cc @@ -24,11 +24,11 @@ bool GLOzoneEGL::InitializeGLOneOffPlatform() { } bool GLOzoneEGL::InitializeStaticGLBindings( - gl::GLImplementation implementation) { + const gl::GLImplementationParts& implementation) { if (!LoadGLES2Bindings(implementation)) return false; - gl::SetGLImplementation(implementation); + gl::SetGLImplementationParts(implementation); gl::InitializeStaticGLBindingsGL(); gl::InitializeStaticGLBindingsEGL(); diff --git a/chromium/ui/ozone/common/gl_ozone_egl.h b/chromium/ui/ozone/common/gl_ozone_egl.h index ec8768347c3..12b7bb70583 100644 --- a/chromium/ui/ozone/common/gl_ozone_egl.h +++ b/chromium/ui/ozone/common/gl_ozone_egl.h @@ -22,7 +22,8 @@ class GLOzoneEGL : public GLOzone { // GLOzone: bool InitializeGLOneOffPlatform() override; - bool InitializeStaticGLBindings(gl::GLImplementation implementation) override; + bool InitializeStaticGLBindings( + const gl::GLImplementationParts& implementation) override; void SetDisabledExtensionsPlatform( const std::string& disabled_extensions) override; bool InitializeExtensionSettingsOneOffPlatform() override; @@ -48,7 +49,8 @@ class GLOzoneEGL : public GLOzone { virtual gl::EGLDisplayPlatform GetNativeDisplay() = 0; // Sets up GL bindings for the native surface. - virtual bool LoadGLES2Bindings(gl::GLImplementation implementation) = 0; + virtual bool LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) = 0; private: DISALLOW_COPY_AND_ASSIGN(GLOzoneEGL); diff --git a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc index c0efb5df87e..fd6026ae4f3 100644 --- a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc +++ b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc @@ -17,10 +17,6 @@ OzoneUIControlsTestHelper* PrintErrorAndReturnNullptr() { } } // namespace -OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWayland() { - return PrintErrorAndReturnNullptr(); -} - OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWindows() { return PrintErrorAndReturnNullptr(); } diff --git a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h index 8146a5a231e..94fa715dc63 100644 --- a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h +++ b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h @@ -9,7 +9,6 @@ namespace ui { class OzoneUIControlsTestHelper; -OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWayland(); OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWindows(); OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperDrm(); OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperScenic(); diff --git a/chromium/ui/ozone/demo/demo_window.cc b/chromium/ui/ozone/demo/demo_window.cc index caf78c25e89..70d688e324c 100644 --- a/chromium/ui/ozone/demo/demo_window.cc +++ b/chromium/ui/ozone/demo/demo_window.cc @@ -6,6 +6,7 @@ #include +#include "base/logging.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/events/event.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -65,7 +66,7 @@ void DemoWindow::Quit() { window_manager_->Quit(); } -void DemoWindow::OnBoundsChanged(const gfx::Rect& new_bounds) { +void DemoWindow::OnBoundsChanged(const BoundsChange& change) { StartRendererIfNecessary(); } diff --git a/chromium/ui/ozone/demo/demo_window.h b/chromium/ui/ozone/demo/demo_window.h index 907107b1070..ecfb94061fb 100644 --- a/chromium/ui/ozone/demo/demo_window.h +++ b/chromium/ui/ozone/demo/demo_window.h @@ -35,7 +35,7 @@ class DemoWindow : public PlatformWindowDelegate { void Quit(); // PlatformWindowDelegate: - void OnBoundsChanged(const gfx::Rect& new_bounds) override; + void OnBoundsChanged(const BoundsChange& change) override; void OnDamageRect(const gfx::Rect& damaged_region) override; void DispatchEvent(Event* event) override; void OnCloseRequest() override; diff --git a/chromium/ui/ozone/demo/ozone_demo.cc b/chromium/ui/ozone/demo/ozone_demo.cc index bb639f0871b..daffeab8d0d 100644 --- a/chromium/ui/ozone/demo/ozone_demo.cc +++ b/chromium/ui/ozone/demo/ozone_demo.cc @@ -8,6 +8,7 @@ #include "base/at_exit.h" #include "base/command_line.h" #include "base/debug/stack_trace.h" +#include "base/logging.h" #include "base/message_loop/message_pump_type.h" #include "base/run_loop.h" #include "base/task/single_thread_task_executor.h" diff --git a/chromium/ui/ozone/demo/skia/skia_demo.cc b/chromium/ui/ozone/demo/skia/skia_demo.cc index d3bc9d7acff..71e8385bfbe 100644 --- a/chromium/ui/ozone/demo/skia/skia_demo.cc +++ b/chromium/ui/ozone/demo/skia/skia_demo.cc @@ -8,6 +8,7 @@ #include "base/at_exit.h" #include "base/command_line.h" #include "base/debug/stack_trace.h" +#include "base/logging.h" #include "base/message_loop/message_pump_type.h" #include "base/run_loop.h" #include "base/task/single_thread_task_executor.h" diff --git a/chromium/ui/ozone/demo/window_manager.cc b/chromium/ui/ozone/demo/window_manager.cc index 686f88da6ce..d99ec80bd5e 100644 --- a/chromium/ui/ozone/demo/window_manager.cc +++ b/chromium/ui/ozone/demo/window_manager.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/logging.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/display/types/display_snapshot.h" #include "ui/display/types/native_display_delegate.h" 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 93ed64dafb0..e45b1ad3afd 100644 --- a/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc +++ b/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.cc @@ -132,7 +132,8 @@ bool GLOzoneEglCast::ResizeDisplay(gfx::Size size) { return true; } -bool GLOzoneEglCast::LoadGLES2Bindings(gl::GLImplementation implementation) { +bool GLOzoneEglCast::LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) { InitializeHardwareIfNeeded(); void* lib_egl = egl_platform_->GetEglLibrary(); diff --git a/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.h b/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.h index 79bcfd833ca..1feea0520c6 100644 --- a/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.h +++ b/chromium/ui/ozone/platform/cast/gl_ozone_egl_cast.h @@ -33,7 +33,8 @@ class GLOzoneEglCast : public GLOzoneEGL { scoped_refptr CreateOffscreenGLSurface( const gfx::Size& size) override; gl::EGLDisplayPlatform GetNativeDisplay() override; - bool LoadGLES2Bindings(gl::GLImplementation implementation) override; + bool LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) override; intptr_t GetNativeWindow(); bool ResizeDisplay(gfx::Size viewport_size); diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc index 4ebb9c3eebc..aaebad04a50 100644 --- a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc +++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc @@ -105,8 +105,9 @@ SurfaceFactoryCast::GetAllowedGLImplementations() { return impls; } -GLOzone* SurfaceFactoryCast::GetGLOzone(gl::GLImplementation implementation) { - switch (implementation) { +GLOzone* SurfaceFactoryCast::GetGLOzone( + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationEGLGLES2: return egl_implementation_.get(); default: diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.h b/chromium/ui/ozone/platform/cast/surface_factory_cast.h index ea3ad0ff7d0..de582c61b4a 100644 --- a/chromium/ui/ozone/platform/cast/surface_factory_cast.h +++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.h @@ -30,7 +30,7 @@ class SurfaceFactoryCast : public SurfaceFactoryOzone { // SurfaceFactoryOzone implementation: std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; std::unique_ptr CreateCanvasForWidget( gfx::AcceleratedWidget widget) override; scoped_refptr CreateNativePixmap( diff --git a/chromium/ui/ozone/platform/drm/BUILD.gn b/chromium/ui/ozone/platform/drm/BUILD.gn index 5e5c1eb225c..072cf6fa7f7 100644 --- a/chromium/ui/ozone/platform/drm/BUILD.gn +++ b/chromium/ui/ozone/platform/drm/BUILD.gn @@ -133,6 +133,7 @@ source_set("gbm") { "//ui/base", "//ui/base/cursor", "//ui/base/cursor:cursor_base", + "//ui/base/cursor/mojom:cursor_type", "//ui/base/ime", "//ui/display", "//ui/display/types", 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 6f4c17b6fa9..3fde52ddaff 100644 --- a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc +++ b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc @@ -20,8 +20,6 @@ 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/drm_display.cc b/chromium/ui/ozone/platform/drm/gpu/drm_display.cc index b1ccd606e67..2ff0772923c 100644 --- a/chromium/ui/ozone/platform/drm/gpu/drm_display.cc +++ b/chromium/ui/ozone/platform/drm/gpu/drm_display.cc @@ -166,6 +166,8 @@ std::unique_ptr DrmDisplay::Update( return params; } +// When reading DRM state always check that it's still valid. Any sort of events +// (such as disconnects) may invalidate the state. bool DrmDisplay::GetHDCPState( display::HDCPState* state, display::ContentProtectionMethod* protection_method) { @@ -183,6 +185,11 @@ bool DrmDisplay::GetHDCPState( ScopedDrmObjectPropertyPtr property_values(drm_->GetObjectProperties( connector_->connector_id, DRM_MODE_OBJECT_CONNECTOR)); + if (!property_values) { + PLOG(INFO) << "Properties no longer valid for connector " + << connector_->connector_id << "."; + return false; + } std::string name = GetEnumNameForProperty(property_values.get(), hdcp_property.get()); size_t i; 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 f5938777c47..76577c6e485 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,16 +81,15 @@ class DrmOverlayValidatorTest : public testing::Test { bool ModesetController(ui::HardwareDisplayController* controller) { ui::CommitRequest commit_request; - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); + ui::DrmOverlayPlane plane(CreateBuffer(), nullptr); - controller->GetModesetProps(&commit_request, modeset_planes, kDefaultMode); + controller->GetModesetProps(&commit_request, plane, kDefaultMode); ui::CommitRequest request_for_update = commit_request; bool status = drm_->plane_manager()->Commit(std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET); - - for (const ui::CrtcCommitRequest& crtc_request : commit_request) - controller->UpdateState(crtc_request); + controller->UpdateState( + /*enable_requested=*/true, + ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays())); 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 115231c7d02..4efe7f98c20 100644 --- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc +++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc @@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/message_loop/message_pump_type.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "ui/display/types/display_mode.h" #include "ui/display/types/display_snapshot.h" @@ -277,10 +278,9 @@ void DrmThread::SetWindowBounds(gfx::AcceleratedWidget widget, void DrmThread::SetCursor(gfx::AcceleratedWidget widget, const std::vector& bitmaps, const gfx::Point& location, - int32_t frame_delay_ms) { + base::TimeDelta frame_delay) { TRACE_EVENT0("drm", "DrmThread::SetCursor"); - screen_manager_->GetWindow(widget)->SetCursor(bitmaps, location, - frame_delay_ms); + screen_manager_->GetWindow(widget)->SetCursor(bitmaps, location, frame_delay); } void DrmThread::MoveCursor(gfx::AcceleratedWidget widget, diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h index a58d41063e5..eb00616ac67 100644 --- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h +++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h @@ -175,7 +175,7 @@ class DrmThread : public base::Thread, void SetCursor(gfx::AcceleratedWidget widget, const std::vector& bitmaps, const gfx::Point& location, - int32_t frame_delay_ms) override; + base::TimeDelta frame_delay) override; void MoveCursor(gfx::AcceleratedWidget widget, const gfx::Point& location) override; diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc index d83a4f53d8b..1218b693ada 100644 --- a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc +++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc @@ -67,17 +67,15 @@ void DrmWindow::SetBounds(const gfx::Rect& bounds) { void DrmWindow::SetCursor(const std::vector& bitmaps, const gfx::Point& location, - int frame_delay_ms) { + base::TimeDelta frame_delay) { cursor_bitmaps_ = bitmaps; cursor_location_ = location; cursor_frame_ = 0; - cursor_frame_delay_ms_ = frame_delay_ms; cursor_timer_.Stop(); - if (cursor_frame_delay_ms_) { - cursor_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(cursor_frame_delay_ms_), - this, &DrmWindow::OnCursorAnimationTimeout); + if (!frame_delay.is_zero()) { + cursor_timer_.Start(FROM_HERE, frame_delay, this, + &DrmWindow::OnCursorAnimationTimeout); } ResetCursor(); @@ -131,6 +129,10 @@ 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 ea1ef54b324..8860f6d0494 100644 --- a/chromium/ui/ozone/platform/drm/gpu/drm_window.h +++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.h @@ -22,6 +22,10 @@ class SkBitmap; +namespace base { +class TimeDelta; +} + namespace gfx { class Point; class Rect; @@ -73,7 +77,7 @@ class DrmWindow { // the bitmap is empty, the cursor is hidden. void SetCursor(const std::vector& bitmaps, const gfx::Point& location, - int frame_delay_ms); + base::TimeDelta frame_delay); // Move the HW cursor to the specified location. void MoveCursor(const gfx::Point& location); @@ -84,9 +88,8 @@ class DrmWindow { OverlayStatusList TestPageFlip( const OverlaySurfaceCandidateList& overlay_params); - const DrmOverlayPlaneList& last_submitted_planes() const { - return last_submitted_planes_; - } + // Returns the last buffer associated with this window. + const DrmOverlayPlane* GetLastModesetBuffer() const; private: // Draw next frame in an animated cursor. @@ -115,7 +118,6 @@ class DrmWindow { std::vector cursor_bitmaps_; gfx::Point cursor_location_; int cursor_frame_ = 0; - int cursor_frame_delay_ms_ = 0; DrmOverlayPlaneList last_submitted_planes_; 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 1edd0cb27c0..9b45a480ebd 100644 --- a/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc +++ b/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc @@ -15,6 +15,7 @@ #include "base/files/platform_file.h" #include "base/macros.h" #include "base/test/task_environment.h" +#include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" @@ -250,7 +251,7 @@ TEST_F(DrmWindowTest, SetCursorImage) { const gfx::Size cursor_size(6, 4); screen_manager_->GetWindow(kDefaultWidgetHandle) ->SetCursor(std::vector(1, AllocateBitmap(cursor_size)), - gfx::Point(4, 2), 0); + gfx::Point(4, 2), base::TimeDelta()); SkBitmap cursor; std::vector> cursor_buffers = GetCursorBuffers(drm_); @@ -276,7 +277,7 @@ TEST_F(DrmWindowTest, CheckCursorSurfaceAfterChangingDevice) { const gfx::Size cursor_size(6, 4); screen_manager_->GetWindow(kDefaultWidgetHandle) ->SetCursor(std::vector(1, AllocateBitmap(cursor_size)), - gfx::Point(4, 2), 0); + gfx::Point(4, 2), base::TimeDelta()); // Add another device. auto gbm_device = std::make_unique(); 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 2fdc72f9a49..d4ba6cf2727 100644 --- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc +++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc @@ -162,7 +162,7 @@ class GLOzoneEGLGbm : public GLOzoneEGL { return native_display_; } - bool LoadGLES2Bindings(gl::GLImplementation impl) override { + bool LoadGLES2Bindings(const gl::GLImplementationParts& impl) override { return LoadDefaultEGLGLES2Bindings(impl); } @@ -264,8 +264,9 @@ GbmSurfaceFactory::GetAllowedGLImplementations() { gl::kGLImplementationSwiftShaderGL}; } -GLOzone* GbmSurfaceFactory::GetGLOzone(gl::GLImplementation implementation) { - switch (implementation) { +GLOzone* GbmSurfaceFactory::GetGLOzone( + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationEGLGLES2: case gl::kGLImplementationSwiftShaderGL: case gl::kGLImplementationEGLANGLE: 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 4aa40139d7d..ab34bda5b20 100644 --- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h +++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h @@ -35,7 +35,7 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone { // SurfaceFactoryOzone: std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; #if BUILDFLAG(ENABLE_VULKAN) std::unique_ptr CreateVulkanImplementation( 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 ed387cbc7dc..6c4f07658cc 100644 --- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc +++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc @@ -43,12 +43,13 @@ namespace { void CompletePageFlip( base::WeakPtr hardware_display_controller_, + int modeset_sequence, PresentationOnceCallback callback, DrmOverlayPlaneList plane_list, const gfx::PresentationFeedback& presentation_feedback) { if (hardware_display_controller_) { - hardware_display_controller_->OnPageFlipComplete(std::move(plane_list), - presentation_feedback); + hardware_display_controller_->OnPageFlipComplete( + modeset_sequence, std::move(plane_list), presentation_feedback); } std::move(callback).Run(presentation_feedback); } @@ -75,26 +76,24 @@ HardwareDisplayController::HardwareDisplayController( HardwareDisplayController::~HardwareDisplayController() = default; -void HardwareDisplayController::GetModesetProps( - CommitRequest* commit_request, - const DrmOverlayPlaneList& modeset_planes, - const drmModeModeInfo& mode) { - GetModesetPropsForCrtcs(commit_request, modeset_planes, +void HardwareDisplayController::GetModesetProps(CommitRequest* commit_request, + const DrmOverlayPlane& primary, + const drmModeModeInfo& mode) { + GetModesetPropsForCrtcs(commit_request, primary, /*use_current_crtc_mode=*/false, mode); } -void HardwareDisplayController::GetEnableProps( - CommitRequest* commit_request, - const DrmOverlayPlaneList& modeset_planes) { +void HardwareDisplayController::GetEnableProps(CommitRequest* commit_request, + const DrmOverlayPlane& primary) { // TODO(markyacoub): Simplify and remove the use of empty_mode. drmModeModeInfo empty_mode = {}; - GetModesetPropsForCrtcs(commit_request, modeset_planes, + GetModesetPropsForCrtcs(commit_request, primary, /*use_current_crtc_mode=*/true, empty_mode); } void HardwareDisplayController::GetModesetPropsForCrtcs( CommitRequest* commit_request, - const DrmOverlayPlaneList& modeset_planes, + const DrmOverlayPlane& primary, bool use_current_crtc_mode, const drmModeModeInfo& mode) { DCHECK(commit_request); @@ -105,7 +104,8 @@ void HardwareDisplayController::GetModesetPropsForCrtcs( drmModeModeInfo modeset_mode = use_current_crtc_mode ? controller->mode() : mode; - DrmOverlayPlaneList overlays = DrmOverlayPlane::Clone(modeset_planes); + DrmOverlayPlaneList overlays; + overlays.push_back(primary.Clone()); CrtcCommitRequest request = CrtcCommitRequest::EnableCrtcRequest( controller->crtc(), controller->connector(), modeset_mode, origin_, @@ -123,13 +123,14 @@ void HardwareDisplayController::GetDisableProps(CommitRequest* commit_request) { } void HardwareDisplayController::UpdateState( - const CrtcCommitRequest& crtc_request) { + bool enable_requested, + const DrmOverlayPlane* primary_plane) { // Verify that the current state matches the requested state. - if (crtc_request.should_enable() && IsEnabled()) { - DCHECK(!crtc_request.overlays().empty()); + if (enable_requested && IsEnabled()) { + DCHECK(primary_plane); // TODO(markyacoub): This should be absorbed in the commit request. ResetCursor(); - OnModesetComplete(crtc_request.overlays()); + OnModesetComplete(*primary_plane); } } @@ -180,6 +181,7 @@ void HardwareDisplayController::SchedulePageFlip( // Everything was submitted successfully, wait for asynchronous completion. page_flip_request->TakeCallback( base::BindOnce(&CompletePageFlip, weak_ptr_factory_.GetWeakPtr(), + GetDrmDevice()->modeset_sequence_id(), std::move(presentation_callback), std::move(plane_list))); page_flip_request_ = std::move(page_flip_request); } @@ -241,13 +243,23 @@ std::vector HardwareDisplayController::GetFormatModifiers( } std::vector HardwareDisplayController::GetSupportedModifiers( - uint32_t fourcc_format) const { + uint32_t fourcc_format, + bool is_modeset) const { if (preferred_format_modifier_.empty()) return std::vector(); auto it = preferred_format_modifier_.find(fourcc_format); - if (it != preferred_format_modifier_.end()) - return std::vector{it->second}; + if (it != preferred_format_modifier_.end()) { + uint64_t supported_modifier = it->second; + // AFBC for modeset buffers doesn't work correctly, as we can't fill it with + // a valid AFBC buffer (crbug.com/852675). + // For now, don't use AFBC for modeset buffers. + if (is_modeset && + supported_modifier == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) { + supported_modifier = DRM_FORMAT_MOD_LINEAR; + } + return std::vector{supported_modifier}; + } return GetFormatModifiers(fourcc_format); } @@ -257,19 +269,7 @@ HardwareDisplayController::GetFormatModifiersForTestModeset( uint32_t fourcc_format) { // If we're about to test, clear the current preferred modifier. preferred_format_modifier_.clear(); - - std::vector filtered_modifiers; - const auto& modifiers = GetFormatModifiers(fourcc_format); - for (auto modifier : modifiers) { - // AFBC for modeset buffers doesn't work correctly, as we can't fill it with - // a valid AFBC buffer. For now, don't use AFBC for modeset buffers. - // TODO: Use AFBC for modeset buffers if it is available. - // See https://crbug.com/852675. - if (modifier != DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) { - filtered_modifiers.push_back(modifier); - } - } - return filtered_modifiers; + return GetFormatModifiers(fourcc_format); } void HardwareDisplayController::UpdatePreferredModiferForFormat( @@ -403,28 +403,36 @@ scoped_refptr HardwareDisplayController::GetDrmDevice() const { } void HardwareDisplayController::OnPageFlipComplete( + int modeset_sequence, DrmOverlayPlaneList pending_planes, const gfx::PresentationFeedback& presentation_feedback) { if (!page_flip_request_) return; // Modeset occured during this page flip. + time_of_last_flip_ = presentation_feedback.timestamp; current_planes_ = std::move(pending_planes); + for (const auto& controller : crtc_controllers_) { - GetDrmDevice()->plane_manager()->ResetModesetStateForCrtc( - controller->crtc()); + // 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( + controller->crtc()); + } } page_flip_request_ = nullptr; } void HardwareDisplayController::OnModesetComplete( - 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. + 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. page_flip_request_ = nullptr; owned_hardware_planes_.legacy_page_flips.clear(); - current_planes_ = DrmOverlayPlane::Clone(modeset_planes); + current_planes_.clear(); + current_planes_.push_back(primary.Clone()); 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 27e4dd4bcbf..4cd323a8c39 100644 --- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h +++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h @@ -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 DrmOverlayPlaneList& modeset_planes, + const DrmOverlayPlane& primary, const drmModeModeInfo& mode); // Gets the props required to enable/disable a CRTC onto |commit_request|. void GetEnableProps(CommitRequest* commit_request, - const DrmOverlayPlaneList& modeset_planes); + const DrmOverlayPlane& primary); void GetDisableProps(CommitRequest* commit_request); // Updates state of the controller after modeset/enable/disable is performed. - void UpdateState(const CrtcCommitRequest& crtc_request); + void UpdateState(bool enable_requested, const DrmOverlayPlane* primary_plane); // Schedules the |overlays|' framebuffers to be displayed on the next vsync // event. The event will be posted on the graphics card file descriptor |fd_| @@ -131,13 +131,9 @@ class HardwareDisplayController { bool TestPageFlip(const DrmOverlayPlaneList& plane_list); // Return the supported modifiers for |fourcc_format| for this controller. - std::vector GetSupportedModifiers(uint32_t fourcc_format) const; + std::vector GetSupportedModifiers(uint32_t fourcc_format, + bool is_modeset = false) const; - // Return the supported modifiers for |fourcc_format| for this - // controller to be used for modeset buffers. Currently, this only exists - // because we can't provide valid AFBC buffers during modeset. - // See https://crbug.com/852675 - // TODO: Remove this. std::vector GetFormatModifiersForTestModeset( uint32_t fourcc_format); @@ -172,6 +168,7 @@ class HardwareDisplayController { scoped_refptr GetDrmDevice() const; void OnPageFlipComplete( + int modeset_sequence, DrmOverlayPlaneList pending_planes, const gfx::PresentationFeedback& presentation_feedback); @@ -179,10 +176,10 @@ class HardwareDisplayController { // Loops over |crtc_controllers_| and save their props into |commit_request| // to be enabled/modeset. void GetModesetPropsForCrtcs(CommitRequest* commit_request, - const DrmOverlayPlaneList& modeset_planes, + const DrmOverlayPlane& primary, bool use_current_crtc_mode, const drmModeModeInfo& mode); - void OnModesetComplete(const DrmOverlayPlaneList& modeset_planes); + void OnModesetComplete(const DrmOverlayPlane& primary); bool ScheduleOrTestPageFlip(const DrmOverlayPlaneList& plane_list, scoped_refptr page_flip_request, std::unique_ptr* out_fence); 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 7cc0dddf155..8a306182295 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,7 +9,6 @@ #include #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" @@ -124,7 +123,7 @@ class HardwareDisplayControllerTest : public testing::Test { } protected: - bool ModesetWithPlanes(const ui::DrmOverlayPlaneList& modeset_planes); + bool ModesetWithPlane(const ui::DrmOverlayPlane& plane); bool DisableController(); std::unique_ptr controller_; @@ -243,15 +242,16 @@ void HardwareDisplayControllerTest::InitializeDrmDevice(bool use_atomic) { gfx::Point()); } -bool HardwareDisplayControllerTest::ModesetWithPlanes( - const ui::DrmOverlayPlaneList& modeset_planes) { +bool HardwareDisplayControllerTest::ModesetWithPlane( + const ui::DrmOverlayPlane& plane) { ui::CommitRequest commit_request; - controller_->GetModesetProps(&commit_request, modeset_planes, kDefaultMode); + controller_->GetModesetProps(&commit_request, plane, kDefaultMode); ui::CommitRequest request_for_update = commit_request; bool status = drm_->plane_manager()->Commit(std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET); - for (const ui::CrtcCommitRequest& crtc_request : commit_request) - controller_->UpdateState(crtc_request); + controller_->UpdateState( + /*enable_requested=*/true, + ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays())); return status; } @@ -262,8 +262,7 @@ 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); - for (const ui::CrtcCommitRequest& crtc_request : commit_request) - controller_->UpdateState(crtc_request); + controller_->UpdateState(/*enable_requested=*/false, nullptr); return status; } @@ -302,18 +301,15 @@ uint64_t HardwareDisplayControllerTest::GetPlanePropertyValue( } TEST_F(HardwareDisplayControllerTest, CheckModesettingResult) { - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); + ui::DrmOverlayPlane plane(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); - EXPECT_FALSE(ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes) - ->buffer->HasOneRef()); + EXPECT_TRUE(ModesetWithPlane(plane)); + EXPECT_FALSE(plane.buffer->HasOneRef()); } TEST_F(HardwareDisplayControllerTest, CrtcPropsAfterModeset) { - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); ui::ScopedDrmObjectPropertyPtr crtc_props = drm_->GetObjectProperties(kPrimaryCrtc, DRM_MODE_OBJECT_CRTC); @@ -332,9 +328,8 @@ TEST_F(HardwareDisplayControllerTest, CrtcPropsAfterModeset) { } TEST_F(HardwareDisplayControllerTest, ConnectorPropsAfterModeset) { - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); ui::ScopedDrmObjectPropertyPtr connector_props = drm_->GetObjectProperties(kConnectorIdBase, DRM_MODE_OBJECT_CONNECTOR); @@ -348,15 +343,11 @@ TEST_F(HardwareDisplayControllerTest, ConnectorPropsAfterModeset) { TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) { const FakeFenceFD fake_fence_fd; - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), fake_fence_fd.GetGpuFence()); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), fake_fence_fd.GetGpuFence()); + EXPECT_TRUE(ModesetWithPlane(plane1)); 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); @@ -367,13 +358,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(primary_plane->display_bounds.x(), static_cast(prop.value)); + EXPECT_EQ(plane1.display_bounds.x(), static_cast(prop.value)); } { ui::DrmDevice::Property prop = {}; ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_Y", &prop); EXPECT_EQ(kCrtcY, prop.id); - EXPECT_EQ(primary_plane->display_bounds.y(), static_cast(prop.value)); + EXPECT_EQ(plane1.display_bounds.y(), static_cast(prop.value)); } { ui::DrmDevice::Property prop = {}; @@ -391,13 +382,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(primary_plane->buffer->opaque_framebuffer_id(), + EXPECT_EQ(plane1.buffer->opaque_framebuffer_id(), static_cast(prop.value)); } - gfx::RectF crop_rectf = primary_plane->crop_rect; - crop_rectf.Scale(primary_plane->buffer->size().width(), - primary_plane->buffer->size().height()); + gfx::RectF crop_rectf = plane1.crop_rect; + crop_rectf.Scale(plane1.buffer->size().width(), + plane1.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, @@ -436,10 +427,8 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) { } TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) { - ui::DrmOverlayPlaneList modeset_planes; - ui::DrmOverlayPlane plane(CreateBuffer(), nullptr); - modeset_planes.push_back(plane.Clone()); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); // Test invalid fence fd { @@ -454,9 +443,9 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) { } const FakeFenceFD fake_fence_fd; - plane.gpu_fence = fake_fence_fd.GetGpuFence(); + plane1.gpu_fence = fake_fence_fd.GetGpuFence(); std::vector planes = {}; - planes.push_back(plane.Clone()); + planes.push_back(plane1.Clone()); SchedulePageFlip(std::move(planes)); // Verify fence FD after a GPU Fence is added to the plane. @@ -471,10 +460,8 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) { static_cast(fence_fd_prop.value)); } - plane.gpu_fence = nullptr; - modeset_planes.clear(); - modeset_planes.push_back(plane.Clone()); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + plane1.gpu_fence = nullptr; + EXPECT_TRUE(ModesetWithPlane(plane1)); // Test an invalid FD again after the fence is removed. { @@ -490,9 +477,9 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) { } TEST_F(HardwareDisplayControllerTest, CheckDisableResetsProps) { - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + + EXPECT_TRUE(ModesetWithPlane(plane1)); // Test props values after disabling. DisableController(); @@ -594,21 +581,20 @@ TEST_F(HardwareDisplayControllerTest, CheckDisableResetsProps) { } TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) { - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + + EXPECT_TRUE(ModesetWithPlane(plane1)); EXPECT_EQ(1, drm_->get_commit_count()); - ui::DrmOverlayPlane page_flip_plane(CreateBuffer(), nullptr); - std::vector page_flip_planes; - page_flip_planes.push_back(page_flip_plane.Clone()); + ui::DrmOverlayPlane plane2(CreateBuffer(), nullptr); + std::vector planes; + planes.push_back(plane2.Clone()); - SchedulePageFlip(std::move(page_flip_planes)); + SchedulePageFlip(std::move(planes)); drm_->RunCallbacks(); - EXPECT_TRUE(ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes) - ->buffer->HasOneRef()); - EXPECT_FALSE(page_flip_plane.buffer->HasOneRef()); + EXPECT_TRUE(plane1.buffer->HasOneRef()); + EXPECT_FALSE(plane2.buffer->HasOneRef()); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); EXPECT_EQ(1, page_flips_); @@ -622,21 +608,24 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfModesetFails) { InitializeDrmDevice(/* use_atomic */ false); drm_->set_set_crtc_expectation(false); - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_FALSE(ModesetWithPlanes(modeset_planes)); + ui::DrmOverlayPlane plane(CreateBuffer(), nullptr); + + EXPECT_FALSE(ModesetWithPlane(plane)); } TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) { - 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); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + ui::DrmOverlayPlane plane2( + CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE, + gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); + EXPECT_TRUE(ModesetWithPlane(plane1)); EXPECT_EQ(1, drm_->get_commit_count()); + std::vector 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_); @@ -648,15 +637,18 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) { } TEST_F(HardwareDisplayControllerTest, CheckOverlayTestMode) { - 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); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + ui::DrmOverlayPlane plane2( + CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE, + gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); + EXPECT_TRUE(ModesetWithPlane(plane1)); EXPECT_EQ(1, drm_->get_commit_count()); + std::vector 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. @@ -682,13 +674,16 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayTestMode) { } TEST_F(HardwareDisplayControllerTest, AcceptUnderlays) { - 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); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + ui::DrmOverlayPlane plane2(CreateBuffer(), -1, gfx::OVERLAY_TRANSFORM_NONE, + gfx::Rect(kDefaultModeSize), + gfx::RectF(kDefaultModeSizeF), true, nullptr); + + EXPECT_TRUE(ModesetWithPlane(plane1)); - EXPECT_TRUE(ModesetWithPlanes(planes)); + std::vector planes; + planes.push_back(plane1.Clone()); + planes.push_back(plane2.Clone()); SchedulePageFlip(std::move(planes)); drm_->RunCallbacks(); @@ -700,12 +695,13 @@ TEST_F(HardwareDisplayControllerTest, PageflipMirroredControllers) { controller_->AddCrtc(std::make_unique( drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1)); - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - - EXPECT_TRUE(ModesetWithPlanes(planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); EXPECT_EQ(1, drm_->get_commit_count()); + ui::DrmOverlayPlane plane2(CreateBuffer(), nullptr); + std::vector planes; + planes.push_back(plane2.Clone()); SchedulePageFlip(std::move(planes)); drm_->RunCallbacks(); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); @@ -724,10 +720,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) { controller_->AddCrtc(std::make_unique( drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1)); - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); - + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); + std::vector planes; + planes.push_back(plane1.Clone()); SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes)); drm_->RunCallbacks(); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); @@ -766,10 +762,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) { } TEST_F(HardwareDisplayControllerTest, PlaneStateAfterDestroyingCrtc) { - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); - + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); + std::vector planes; + planes.push_back(plane1.Clone()); SchedulePageFlip(std::move(planes)); drm_->RunCallbacks(); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); @@ -794,10 +790,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) { controller_->AddCrtc(std::make_unique( drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1)); - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); - + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); + std::vector planes; + planes.push_back(plane1.Clone()); SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes)); drm_->RunCallbacks(); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); @@ -839,52 +835,53 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) { } TEST_F(HardwareDisplayControllerTest, ModesetWhilePageFlipping) { - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); - - SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes)); + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); + std::vector planes; + planes.push_back(plane1.Clone()); + SchedulePageFlip(std::move(planes)); - EXPECT_TRUE(ModesetWithPlanes(planes)); + EXPECT_TRUE(ModesetWithPlane(plane1)); drm_->RunCallbacks(); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); EXPECT_EQ(1, page_flips_); } TEST_F(HardwareDisplayControllerTest, FailPageFlipping) { - ui::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - ASSERT_TRUE(ModesetWithPlanes(modeset_planes)); - - std::vector page_flip_planes; - page_flip_planes.emplace_back(CreateBuffer(), nullptr); + ASSERT_TRUE(ModesetWithPlane(ui::DrmOverlayPlane(CreateBuffer(), nullptr))); drm_->set_commit_expectation(false); - EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(page_flip_planes)), + ui::DrmOverlayPlane post_modeset_plane(CreateBuffer(), nullptr); + + std::vector planes; + planes.push_back(post_modeset_plane.Clone()); + EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(planes)), "SchedulePageFlip failed"); } TEST_F(HardwareDisplayControllerTest, RecreateBuffersOnOldPlanesPageFlipFailure) { - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - ASSERT_TRUE(ModesetWithPlanes(planes)); + ui::DrmOverlayPlane pre_modeset_plane(CreateBuffer(), nullptr); + ASSERT_TRUE(ModesetWithPlane(pre_modeset_plane)); drm_->set_commit_expectation(false); + + std::vector 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::DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(modeset_planes)); - - std::vector 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)); + 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 planes; + planes.push_back(plane1.Clone()); + SchedulePageFlip(std::move(planes)); drm_->RunCallbacks(); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); @@ -892,10 +889,10 @@ TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlaneOnFlip) { } TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) { - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); - + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); + std::vector planes; + planes.push_back(plane1.Clone()); SchedulePageFlip(std::move(planes)); controller_->AddCrtc(std::make_unique( @@ -907,10 +904,10 @@ TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) { } TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) { - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); - + ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); + EXPECT_TRUE(ModesetWithPlane(plane1)); + std::vector planes; + planes.push_back(plane1.Clone()); SchedulePageFlip(std::move(planes)); controller_->RemoveCrtc(drm_, kPrimaryCrtc); @@ -924,13 +921,16 @@ TEST_F(HardwareDisplayControllerTest, Disable) { // Page flipping overlays is only supported on atomic configurations. InitializeDrmDevice(/* use_atomic= */ true); - ui::DrmOverlayPlaneList planes; - planes.emplace_back(CreateBuffer(), nullptr); - EXPECT_TRUE(ModesetWithPlanes(planes)); + 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 planes; + planes.push_back(plane1.Clone()); + planes.push_back(plane2.Clone()); - 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_); @@ -946,19 +946,50 @@ TEST_F(HardwareDisplayControllerTest, Disable) { ASSERT_EQ(0, planes_in_use); } -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)); +TEST_F(HardwareDisplayControllerTest, PageflipAfterModeset) { + scoped_refptr buffer = CreateBuffer(); + ui::DrmOverlayPlane plane1(buffer, nullptr); + + ModesetWithPlane(plane1); + EXPECT_EQ(drm_->plane_manager() ->GetCrtcStateForCrtcId(kPrimaryCrtc) - .modeset_framebuffers.size(), - 2UL); - for (const auto& plane : modeset_planes) { - EXPECT_TRUE(base::Contains(drm_->plane_manager() - ->GetCrtcStateForCrtcId(kPrimaryCrtc) - .modeset_framebuffers, - plane.buffer)); - } + .modeset_framebuffer, + buffer); + + std::vector 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); +} + +TEST_F(HardwareDisplayControllerTest, PageflipBeforeModeset) { + scoped_refptr buffer = CreateBuffer(); + ui::DrmOverlayPlane plane1(buffer, nullptr); + + EXPECT_TRUE(ModesetWithPlane(ui::DrmOverlayPlane(CreateBuffer(), nullptr))); + + std::vector planes; + planes.push_back(plane1.Clone()); + SchedulePageFlip(std::move(planes)); + + EXPECT_TRUE(ModesetWithPlane(plane1)); + EXPECT_EQ(drm_->plane_manager() + ->GetCrtcStateForCrtcId(kPrimaryCrtc) + .modeset_framebuffer, + buffer); + + // modeset_framebuffer should not be cleared when a pageflip callback is run + // after a modeset + drm_->RunCallbacks(); + EXPECT_EQ(drm_->plane_manager() + ->GetCrtcStateForCrtcId(kPrimaryCrtc) + .modeset_framebuffer, + 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 448cfa9a14b..634fb042481 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,10 +459,8 @@ void HardwareDisplayPlaneManager::UpdateCrtcAndPlaneStatesAfterModeset( if (is_enabled) { crtc_state.mode = crtc_request.mode(); - crtc_state.modeset_framebuffers.clear(); - for (const auto& overlay : crtc_request.overlays()) - crtc_state.modeset_framebuffers.push_back(overlay.buffer); - + crtc_state.modeset_framebuffer = + DrmOverlayPlane::GetPrimaryPlane(crtc_request.overlays())->buffer; } else { if (crtc_request.plane_list()) disable_planes_lists.insert(crtc_request.plane_list()); @@ -485,9 +483,9 @@ void HardwareDisplayPlaneManager::UpdateCrtcAndPlaneStatesAfterModeset( } } -void HardwareDisplayPlaneManager::ResetModesetStateForCrtc(uint32_t crtc_id) { +void HardwareDisplayPlaneManager::ResetModesetBufferOfCrtc(uint32_t crtc_id) { CrtcState& crtc_state = CrtcStateForCrtcId(crtc_id); - crtc_state.modeset_framebuffers.clear(); + crtc_state.modeset_framebuffer = nullptr; } } // 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 0cd18997ce8..a4593292e8d 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 @@ -82,7 +82,7 @@ class HardwareDisplayPlaneManager { CrtcState(CrtcState&&); drmModeModeInfo mode = {}; - std::vector> modeset_framebuffers; + scoped_refptr modeset_framebuffer; CrtcProperties properties = {}; @@ -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 ResetModesetStateForCrtc(uint32_t crtc_id); + void ResetModesetBufferOfCrtc(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 2fae9fcc8ff..3b8c3eec755 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 @@ -142,11 +142,8 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(CommitRequest commit_request, if (crtc_request.should_enable()) { DCHECK(crtc_request.plane_list()); - if (!AssignOverlayPlanes(crtc_request.plane_list(), - crtc_request.overlays(), crtc_id)) { - LOG_IF(ERROR, !is_testing) << "Failed to Assign Overlay Planes"; - status = false; - } + status &= AssignOverlayPlanes(crtc_request.plane_list(), + crtc_request.overlays(), crtc_id); enable_planes_lists.insert(crtc_request.plane_list()); } } @@ -368,7 +365,7 @@ void HardwareDisplayPlaneManagerAtomic::RequestPlanesReadyCallback( } bool HardwareDisplayPlaneManagerAtomic::SetPlaneData( - HardwareDisplayPlaneList*, + HardwareDisplayPlaneList* plane_list, HardwareDisplayPlane* hw_plane, const DrmOverlayPlane& overlay, uint32_t crtc_id, 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 1ef0fe9f11f..fe24499014c 100644 --- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc +++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc @@ -10,7 +10,6 @@ #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" @@ -182,24 +181,6 @@ 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& 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( @@ -487,10 +468,8 @@ bool MockDrmDevice::CommitPropertiesInternal( } uint64_t requested_resources = 0; - base::flat_map crtc_planes_counter; - for (uint32_t i = 0; i < request->cursor; ++i) { - const drmModeAtomicReqItem& item = request->items[i]; + const auto& item = request->items[i]; if (!ValidatePropertyValue(item.property_id, item.value)) return false; @@ -498,12 +477,6 @@ 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_) { @@ -527,12 +500,6 @@ 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 0c2d823f12a..bdf09aa3b5c 100644 --- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h +++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h @@ -92,18 +92,11 @@ 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> 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; @@ -231,7 +224,6 @@ 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_; @@ -239,10 +231,8 @@ 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> buffers_; diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc index 127f4d87257..e54b8cf58d0 100644 --- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc +++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc @@ -234,14 +234,8 @@ 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; - 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); + config_success &= + TestModeset(controllers_params) && Modeset(controllers_params); } if (config_success) @@ -250,6 +244,12 @@ 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,21 +269,19 @@ bool ScreenManager::TestAndSetPreferredModifiers( display::DisplaySnapshot::PrimaryFormat()); std::vector modifiers = controller->GetFormatModifiersForTestModeset(fourcc_format); - // Test with no overlays to go for a lower bandwidth usage. - DrmOverlayPlaneList modeset_planes = GetModesetPlanes( + + DrmOverlayPlane primary_plane = GetModesetBuffer( controller, gfx::Rect(params.origin, ModeSize(*params.mode)), - modifiers, /*include_overlays=*/false, /*is_testing=*/true); - if (modeset_planes.empty()) + modifiers, /*is_testing=*/true); + if (!primary_plane.buffer) { return false; + } - uint64_t primary_modifier = - DrmOverlayPlane::GetPrimaryPlane(modeset_planes) - ->buffer->format_modifier(); - crtcs_preferred_modifier[params.crtc] = - std::make_pair(modifiers.empty(), primary_modifier); + crtcs_preferred_modifier[params.crtc] = std::make_pair( + modifiers.empty(), primary_plane.buffer->format_modifier()); GetModesetControllerProps(&commit_request, controller, params.origin, - *params.mode, modeset_planes); + *params.mode, primary_plane); } else { controller->GetDisableProps(&commit_request); } @@ -327,15 +325,14 @@ bool ScreenManager::TestAndSetLinearModifier( std::make_pair(modifiers.empty(), DRM_FORMAT_MOD_LINEAR); if (params.mode) { - // Test with no overlays to go for a lower bandwidth usage. - DrmOverlayPlaneList modeset_planes = GetModesetPlanes( + DrmOverlayPlane primary_plane = GetModesetBuffer( controller, gfx::Rect(params.origin, ModeSize(*params.mode)), - modifiers, /*include_overlays=*/false, /*is_testing=*/true); - if (modeset_planes.empty()) + modifiers, /*is_testing=*/true); + if (!primary_plane.buffer) return false; GetModesetControllerProps(&commit_request, controller, params.origin, - *params.mode, modeset_planes); + *params.mode, primary_plane); } else { controller->GetDisableProps(&commit_request); } @@ -373,54 +370,10 @@ void ScreenManager::SetPreferredModifiers( } } -bool ScreenManager::TestModesetWithOverlays( - const ControllerConfigsList& controllers_params) { - TRACE_EVENT1("drm", "ScreenManager::TestModesetWithOverlays", "display_count", +bool ScreenManager::Modeset(const ControllerConfigsList& controllers_params) { + TRACE_EVENT1("drm", "ScreenManager::Modeset", "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 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; @@ -433,16 +386,16 @@ bool ScreenManager::Modeset(const ControllerConfigsList& controllers_params, uint32_t fourcc_format = GetFourCCFormatForOpaqueFramebuffer( display::DisplaySnapshot::PrimaryFormat()); std::vector modifiers = - controller->GetSupportedModifiers(fourcc_format); - - gfx::Rect bounds = gfx::Rect(params.origin, ModeSize(*params.mode)); - DrmOverlayPlaneList modeset_planes = - GetModesetPlanes(controller, bounds, modifiers, - can_modeset_with_overlays, /*is_testing=*/false); + 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; SetDisplayControllerForEnableAndGetProps( &commit_request, params.drm, params.crtc, params.connector, - params.origin, *params.mode, modeset_planes); + params.origin, *params.mode, primary_plane); } else { bool disable_set = SetDisableDisplayControllerForDisableAndGetProps( @@ -467,7 +420,7 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps( uint32_t connector, const gfx::Point& origin, const drmModeModeInfo& mode, - const DrmOverlayPlaneList& modeset_planes) { + const DrmOverlayPlane& primary) { HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc); DCHECK(controllers_.end() != it) << "Display controller (crtc=" << crtc << ") doesn't exist."; @@ -484,10 +437,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, modeset_planes); + controller->origin(), mode, primary); } else { // Just get props to re-enable the controller re-using the current state. - GetEnableControllerProps(commit_request, controller, modeset_planes); + GetEnableControllerProps(commit_request, controller, primary); } return; } @@ -503,8 +456,7 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps( controller = it->get(); } - GetModesetControllerProps(commit_request, controller, origin, mode, - modeset_planes); + GetModesetControllerProps(commit_request, controller, origin, mode, primary); } bool ScreenManager::SetDisableDisplayControllerForDisableAndGetProps( @@ -538,7 +490,8 @@ void ScreenManager::UpdateControllerStateAfterModeset( HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc_request.crtc_id()); if (it != controllers_.end()) { - it->get()->UpdateState(crtc_request); + it->get()->UpdateState(was_enabled, DrmOverlayPlane::GetPrimaryPlane( + crtc_request.overlays())); // If the CRTC is mirrored, move it to the mirror controller. if (did_succeed && was_enabled) @@ -673,25 +626,24 @@ void ScreenManager::UpdateControllerToWindowMapping() { display::DisplaySnapshot::PrimaryFormat()); std::vector modifiers = controller->GetSupportedModifiers(fourcc_format); - DrmOverlayPlaneList modeset_planes = GetModesetPlanes( + DrmOverlayPlane primary_plane = GetModesetBuffer( controller, gfx::Rect(controller->origin(), controller->GetModeSize()), modifiers, - /*include_overlays=*/true, /*is_testing=*/false); - DCHECK(!modeset_planes.empty()); + /*is_testing=*/false); + DCHECK(primary_plane.buffer); CommitRequest commit_request; - GetEnableControllerProps(&commit_request, controller, modeset_planes); + GetEnableControllerProps(&commit_request, controller, primary_plane); controller->GetDrmDevice()->plane_manager()->Commit( std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET); } } } -DrmOverlayPlaneList ScreenManager::GetModesetPlanes( +DrmOverlayPlane ScreenManager::GetModesetBuffer( HardwareDisplayController* controller, const gfx::Rect& bounds, const std::vector& modifiers, - bool include_overlays, bool is_testing) { scoped_refptr drm = controller->GetDrmDevice(); uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer( @@ -703,27 +655,19 @@ DrmOverlayPlaneList ScreenManager::GetModesetPlanes( fourcc_format, bounds.size(), GBM_BO_USE_SCANOUT, modifiers); if (!buffer) { LOG(ERROR) << "Failed to create scanout buffer"; - return DrmOverlayPlaneList(); + return DrmOverlayPlane::Error(); } // If the current primary plane matches what we need for the next page flip, - // clone all last_submitted_planes (matching primary + overlays). + // we can clone it. DrmWindow* window = FindWindowAt(bounds); if (window) { - const DrmOverlayPlaneList& last_submitted_planes = - window->last_submitted_planes(); - const DrmOverlayPlane* primary = - DrmOverlayPlane::GetPrimaryPlane(last_submitted_planes); + const DrmOverlayPlane* primary = window->GetLastModesetBuffer(); + const DrmDevice* drm = controller->GetDrmDevice().get(); if (primary && primary->buffer->size() == bounds.size() && - 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; - } + primary->buffer->drm_device() == drm) { + if (primary->buffer->format_modifier() == buffer->GetFormatModifier()) + return primary->Clone(); } } @@ -731,7 +675,7 @@ DrmOverlayPlaneList ScreenManager::GetModesetPlanes( drm, buffer.get(), buffer->GetSize(), modifiers); if (!framebuffer) { LOG(ERROR) << "Failed to add framebuffer for scanout buffer"; - return DrmOverlayPlaneList(); + return DrmOverlayPlane::Error(); } if (!is_testing) { @@ -744,19 +688,16 @@ DrmOverlayPlaneList ScreenManager::GetModesetPlanes( surface->getCanvas()->clear(SK_ColorBLACK); } } - - DrmOverlayPlaneList modeset_planes; - modeset_planes.emplace_back(framebuffer, nullptr); - return modeset_planes; + return DrmOverlayPlane(framebuffer, nullptr); } void ScreenManager::GetEnableControllerProps( CommitRequest* commit_request, HardwareDisplayController* controller, - const DrmOverlayPlaneList& modeset_planes) { + const DrmOverlayPlane& primary) { DCHECK(!controller->crtc_controllers().empty()); - controller->GetEnableProps(commit_request, modeset_planes); + controller->GetEnableProps(commit_request, primary); } void ScreenManager::GetModesetControllerProps( @@ -764,11 +705,11 @@ void ScreenManager::GetModesetControllerProps( HardwareDisplayController* controller, const gfx::Point& origin, const drmModeModeInfo& mode, - const DrmOverlayPlaneList& modeset_planes) { + const DrmOverlayPlane& primary) { DCHECK(!controller->crtc_controllers().empty()); controller->set_origin(origin); - controller->GetModesetProps(commit_request, modeset_planes, mode); + controller->GetModesetProps(commit_request, primary, 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 c102c52525d..d000d3b9499 100644 --- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h +++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h @@ -108,6 +108,7 @@ class ScreenManager { const scoped_refptr& drm, uint32_t crtc); + bool TestModeset(const ControllerConfigsList& controllers_params); bool TestAndSetPreferredModifiers( const ControllerConfigsList& controllers_params); bool TestAndSetLinearModifier( @@ -117,12 +118,8 @@ class ScreenManager { void SetPreferredModifiers( const ControllerConfigsList& controllers_params, const CrtcPreferredModifierMap& crtcs_preferred_modifier); - // 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); + + bool Modeset(const ControllerConfigsList& controllers_params); // Configures a display controller to be enabled. The display controller is // identified by (|crtc|, |connector|) and the controller is to be modeset @@ -134,7 +131,7 @@ class ScreenManager { uint32_t connector, const gfx::Point& origin, const drmModeModeInfo& mode, - const DrmOverlayPlaneList& modeset_planes); + const DrmOverlayPlane& primary); // Configures a display controller to be disabled. The display controller is // identified by |crtc|. Controller modeset props are added into @@ -166,21 +163,20 @@ class ScreenManager { const scoped_refptr& drm, const gfx::Rect& bounds); - DrmOverlayPlaneList GetModesetPlanes(HardwareDisplayController* controller, - const gfx::Rect& bounds, - const std::vector& modifiers, - bool include_overlays, - bool is_testing); + DrmOverlayPlane GetModesetBuffer(HardwareDisplayController* controller, + const gfx::Rect& bounds, + const std::vector& modifiers, + 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 DrmOverlayPlaneList& modeset_planes); + const DrmOverlayPlane& primary); void GetEnableControllerProps(CommitRequest* commit_request, HardwareDisplayController* controller, - const DrmOverlayPlaneList& modeset_planes); + const DrmOverlayPlane& primary); 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 a98d358da52..2e96c2d2f95 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,272 +1467,4 @@ 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 window( - new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); - window->SetBounds(GetPrimaryBounds()); - scoped_refptr 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(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 crtc_states = {{ - /* .planes = */ - { - {/* .formats = */ {DRM_FORMAT_XRGB8888}}, - {/* .formats = */ {DRM_FORMAT_XRGB8888}}, - }, - }}; - InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true); - - std::unique_ptr window( - new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); - window->SetBounds(GetPrimaryBounds()); - scoped_refptr primary = - CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size()); - scoped_refptr 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(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 window( - new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); - window->SetBounds(GetPrimaryBounds()); - scoped_refptr 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(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 crtc_states = {{ - /* .planes = */ - { - {/* .formats = */ {DRM_FORMAT_XRGB8888}}, - {/* .formats = */ {DRM_FORMAT_XRGB8888}}, - }, - }}; - InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true); - - std::unique_ptr window( - new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); - window->SetBounds(GetPrimaryBounds()); - scoped_refptr primary = - CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size()); - scoped_refptr 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(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 crtc_states = {{ - /* .planes = */ - { - {/* .formats = */ {DRM_FORMAT_XRGB8888}}, - {/* .formats = */ {DRM_FORMAT_XRGB8888}}, - }, - }}; - InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true); - - std::unique_ptr window( - new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); - window->SetBounds(GetPrimaryBounds()); - scoped_refptr primary = - CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size()); - scoped_refptr 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(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 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 window( - new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); - window->SetBounds(GetPrimaryBounds()); - - scoped_refptr primary = - CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size()); - scoped_refptr 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(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 5b433602330..49ce7768b42 100644 --- a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc +++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc @@ -7,8 +7,11 @@ #include #include +#include "base/memory/scoped_refptr.h" +#include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/chromeos_buildflags.h" +#include "ui/base/cursor/mojom/cursor_type.mojom.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" @@ -18,9 +21,10 @@ #endif namespace ui { - namespace { +using mojom::CursorType; + class NullProxy : public DrmCursorProxy { public: NullProxy() {} @@ -29,7 +33,7 @@ class NullProxy : public DrmCursorProxy { void CursorSet(gfx::AcceleratedWidget window, const std::vector& bitmaps, const gfx::Point& point, - int frame_delay_ms) override {} + base::TimeDelta frame_delay) override {} void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override {} void InitializeOnEvdevIfNecessary() override {} @@ -75,6 +79,7 @@ void DrmCursor::SetCursor(gfx::AcceleratedWidget window, TRACE_EVENT0("drmcursor", "DrmCursor::SetCursor"); DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_NE(window, gfx::kNullAcceleratedWidget); + DCHECK(platform_cursor); scoped_refptr bitmap = BitmapCursorFactoryOzone::GetBitmapCursor(platform_cursor); @@ -206,7 +211,7 @@ void DrmCursor::MoveCursor(const gfx::Vector2dF& delta) { bool DrmCursor::IsCursorVisible() { base::AutoLock lock(lock_); - return static_cast(bitmap_); + return bitmap_ != nullptr && bitmap_->type() != CursorType::kNone; } gfx::PointF DrmCursor::GetLocation() { @@ -239,21 +244,24 @@ void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location) { } void DrmCursor::SendCursorShowLocked() { - if (!bitmap_) { + if (!bitmap_ || bitmap_->type() == CursorType::kNone) { SendCursorHideLocked(); return; } + CursorSetLockTested(window_, bitmap_->bitmaps(), GetBitmapLocationLocked(), - bitmap_->frame_delay_ms()); + bitmap_->frame_delay()); } void DrmCursor::SendCursorHideLocked() { - CursorSetLockTested(window_, std::vector(), gfx::Point(), 0); + CursorSetLockTested(window_, std::vector(), gfx::Point(), + base::TimeDelta()); } void DrmCursor::SendCursorMoveLocked() { - if (!bitmap_) + if (!bitmap_ || bitmap_->type() == CursorType::kNone) return; + MoveLockTested(window_, GetBitmapLocationLocked()); } @@ -261,9 +269,9 @@ void DrmCursor::SendCursorMoveLocked() { void DrmCursor::CursorSetLockTested(gfx::AcceleratedWidget window, const std::vector& bitmaps, const gfx::Point& point, - int frame_delay_ms) { + base::TimeDelta frame_delay) { lock_.AssertAcquired(); - proxy_->CursorSet(window, bitmaps, point, frame_delay_ms); + proxy_->CursorSet(window, bitmaps, point, frame_delay); } void DrmCursor::MoveLockTested(gfx::AcceleratedWidget window, diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.h b/chromium/ui/ozone/platform/drm/host/drm_cursor.h index 40f751db193..a5d31630e09 100644 --- a/chromium/ui/ozone/platform/drm/host/drm_cursor.h +++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.h @@ -14,6 +14,10 @@ #include "ui/events/ozone/evdev/cursor_delegate_evdev.h" #include "ui/gfx/geometry/rect.h" +namespace base { +class TimeDelta; +} + namespace ui { class BitmapCursorOzone; class DrmWindowHostManager; @@ -25,11 +29,11 @@ class DrmCursorProxy { public: virtual ~DrmCursorProxy() {} - // Sets the cursor |bitmaps| on |window| at |point| with |frame_delay_ms|. + // Sets the cursor |bitmaps| on |window| at |point| with |frame_delay|. virtual void CursorSet(gfx::AcceleratedWidget window, const std::vector& bitmaps, const gfx::Point& point, - int frame_delay_ms) = 0; + base::TimeDelta frame_delay) = 0; // Moves the cursor in |window| to |point|. virtual void Move(gfx::AcceleratedWidget window, const gfx::Point& point) = 0; @@ -83,7 +87,7 @@ class DrmCursor : public CursorDelegateEvdev { void CursorSetLockTested(gfx::AcceleratedWidget window, const std::vector& bitmaps, const gfx::Point& point, - int frame_delay_ms); + base::TimeDelta frame_delay); void MoveLockTested(gfx::AcceleratedWidget window, const gfx::Point& point); // The mutex synchronizing this object. diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc index 32818432bd4..d8d7bc647c4 100644 --- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc +++ b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc @@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" @@ -51,8 +52,40 @@ base::FilePath MapDevPathToSysPath(const base::FilePath& device_path) { // symlink that points to something like // /sys/devices/pci0000:00/0000:00:02.0/0000:05:00.0/drm/card0, which exposes // some metadata about the attached device. - return base::MakeAbsoluteFilePath( + base::FilePath sys_path = base::MakeAbsoluteFilePath( base::FilePath("/sys/class/drm").Append(device_path.BaseName())); + + std::vector components; + sys_path.GetComponents(&components); + base::FilePath path_thus_far; + + for (const auto& component : components) { + if (path_thus_far.empty()) { + path_thus_far = base::FilePath(component); + } else { + path_thus_far = path_thus_far.Append(component); + } + + // Newer versions of the EVDI kernel driver include a symlink to the USB + // device in the sysfs EVDI directory (e.g. + // /sys/devices/platform/evdi.0/device) for EVDI displays that are USB. If + // that symlink exists, read it, and use that path as the sysfs path for the + // display when calculating the association score to match it with a + // corresponding USB touch device. If the symlink doesn't exist, use the + // normal sysfs path. In order to ensure that the sysfs path remains unique, + // append the card name to it. + if (base::StartsWith(component, "evdi", base::CompareCase::SENSITIVE)) { + base::FilePath usb_device_path; + if (base::ReadSymbolicLink(path_thus_far.Append("device"), + &usb_device_path)) { + return base::MakeAbsoluteFilePath(path_thus_far.Append(usb_device_path)) + .Append(device_path.BaseName()); + } + break; + } + } + + return sys_path; } void OpenDeviceAsync(const base::FilePath& device_path, 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 3bce7fcb511..0445d03e05c 100644 --- a/chromium/ui/ozone/platform/drm/host/drm_window_host.cc +++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.cc @@ -85,7 +85,7 @@ gfx::Rect DrmWindowHost::GetBounds() const { return bounds_; } -void DrmWindowHost::SetTitle(const base::string16& title) {} +void DrmWindowHost::SetTitle(const std::u16string& title) {} void DrmWindowHost::SetCapture() { window_manager_->GrabEvents(widget_); 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 c0bd86abcd5..d7000dd0d9b 100644 --- a/chromium/ui/ozone/platform/drm/host/drm_window_host.h +++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.h @@ -63,7 +63,7 @@ class DrmWindowHost : public PlatformWindow, void PrepareForShutdown() override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() const override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void SetCapture() override; void ReleaseCapture() override; bool HasCapture() const override; diff --git a/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc index 2900d45d868..28c65eda2d4 100644 --- a/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc +++ b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc @@ -7,6 +7,7 @@ #include #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "ui/ozone/public/gpu_platform_support_host.h" namespace ui { @@ -39,12 +40,12 @@ HostCursorProxy::~HostCursorProxy() { void HostCursorProxy::CursorSet(gfx::AcceleratedWidget widget, const std::vector& bitmaps, const gfx::Point& location, - int frame_delay_ms) { + base::TimeDelta frame_delay) { if (ui_thread_ref_ == base::PlatformThread::CurrentRef()) { - main_cursor_->SetCursor(widget, bitmaps, location, frame_delay_ms); + main_cursor_->SetCursor(widget, bitmaps, location, frame_delay); } else { InitializeOnEvdevIfNecessary(); - evdev_cursor_->SetCursor(widget, bitmaps, location, frame_delay_ms); + evdev_cursor_->SetCursor(widget, bitmaps, location, frame_delay); } } diff --git a/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h index 05e6ffa05d6..79c85567c69 100644 --- a/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h +++ b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h @@ -32,7 +32,7 @@ class HostCursorProxy : public DrmCursorProxy { void CursorSet(gfx::AcceleratedWidget window, const std::vector& bitmaps, const gfx::Point& point, - int frame_delay_ms) override; + base::TimeDelta frame_delay) override; void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override; void InitializeOnEvdevIfNecessary() override; diff --git a/chromium/ui/ozone/platform/headless/BUILD.gn b/chromium/ui/ozone/platform/headless/BUILD.gn index ca02e70c2cd..8e665de7724 100644 --- a/chromium/ui/ozone/platform/headless/BUILD.gn +++ b/chromium/ui/ozone/platform/headless/BUILD.gn @@ -2,6 +2,8 @@ # 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") { @@ -39,6 +41,10 @@ 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 41cd997bd46..5faeb9d2490 100644 --- a/chromium/ui/ozone/platform/headless/DEPS +++ b/chromium/ui/ozone/platform/headless/DEPS @@ -1,3 +1,4 @@ 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 b3cfb3cf344..b5e46fdb9ea 100644 --- a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc +++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc @@ -201,7 +201,8 @@ class GLOzoneEGLHeadless : public GLOzoneEGL { return gl::EGLDisplayPlatform(EGL_DEFAULT_DISPLAY); } - bool LoadGLES2Bindings(gl::GLImplementation implementation) override { + bool LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) override { return LoadDefaultEGLGLES2Bindings(implementation); } @@ -228,8 +229,8 @@ HeadlessSurfaceFactory::GetAllowedGLImplementations() { } GLOzone* HeadlessSurfaceFactory::GetGLOzone( - gl::GLImplementation implementation) { - switch (implementation) { + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationEGLGLES2: case gl::kGLImplementationSwiftShaderGL: return swiftshader_implementation_.get(); diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.h b/chromium/ui/ozone/platform/headless/headless_surface_factory.h index e11c83eecf4..53dda7b9e45 100644 --- a/chromium/ui/ozone/platform/headless/headless_surface_factory.h +++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.h @@ -22,7 +22,7 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone { // SurfaceFactoryOzone: std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; std::unique_ptr CreateCanvasForWidget( gfx::AcceleratedWidget widget) override; scoped_refptr CreateNativePixmap( diff --git a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc index f6e70bb27fa..0e65df5d378 100644 --- a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc +++ b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc @@ -10,6 +10,7 @@ #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" @@ -29,6 +30,10 @@ #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 @@ -135,6 +140,12 @@ OzonePlatform* CreateOzonePlatformHeadless() { if (cmd->HasSwitch(switches::kOzoneDumpFile)) 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/BUILD.gn b/chromium/ui/ozone/platform/scenic/BUILD.gn index 9cc209840a7..9f9837e76fd 100644 --- a/chromium/ui/ozone/platform/scenic/BUILD.gn +++ b/chromium/ui/ozone/platform/scenic/BUILD.gn @@ -16,6 +16,8 @@ source_set("scenic") { "overlay_manager_scenic.h", "ozone_platform_scenic.cc", "ozone_platform_scenic.h", + "safe_presenter.cc", + "safe_presenter.h", "scenic_gpu_host.cc", "scenic_gpu_host.h", "scenic_gpu_service.cc", @@ -56,8 +58,6 @@ source_set("scenic") { "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.images", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem", - "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.gfx", - "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic", "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp", "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp", "//ui/base", @@ -67,10 +67,16 @@ source_set("scenic") { "//ui/display/fake", "//ui/events:dom_keycode_converter", "//ui/events/ozone/layout", - "//ui/gfx/geometry", "//ui/ozone:ozone_base", "//ui/ozone/common", "//ui/ozone/public/mojom", + ] + + public_deps = [ + "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.gfx", + "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.input", + "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic", + "//ui/gfx/geometry", "//ui/platform_window", ] @@ -88,3 +94,14 @@ source_set("scenic") { ] } } + +source_set("scenic_unittests") { + testonly = true + sources = [ "scenic_window_unittest.cc" ] + deps = [ + ":scenic", + "//base", + "//testing/gtest", + "//ui/ozone:platform", + ] +} diff --git a/chromium/ui/ozone/platform/scenic/safe_presenter.cc b/chromium/ui/ozone/platform/scenic/safe_presenter.cc new file mode 100644 index 00000000000..ed032bf5712 --- /dev/null +++ b/chromium/ui/ozone/platform/scenic/safe_presenter.cc @@ -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. + +#include "ui/ozone/platform/scenic/safe_presenter.h" + +#include +#include + +#include "base/check.h" + +namespace ui { + +SafePresenter::SafePresenter(scenic::Session* session) : session_(session) { + DCHECK(session_); + + session_->set_on_frame_presented_handler( + fit::bind_member(this, &SafePresenter::OnFramePresented)); +} + +SafePresenter::~SafePresenter() = default; + +void SafePresenter::QueuePresent() { + // Present to Scenic immediately, if we can. + if (presents_allowed_) { + QueuePresentHelper(); + return; + } + + // We cannot present immediately, so queue for later. + present_queued_ = true; +} + +void SafePresenter::QueuePresentHelper() { + DCHECK(session_); + DCHECK(presents_allowed_); + + presents_allowed_ = false; + present_queued_ = false; + session_->Present2(/*requested_presentation_time=*/0, + /*requested_prediction_span=*/0, [](auto) {}); +} + +void SafePresenter::OnFramePresented( + fuchsia::scenic::scheduling::FramePresentedInfo info) { + presents_allowed_ = info.num_presents_allowed > 0; + // Since we only have one Present2 call in progress at once, this must + // be true. + DCHECK(presents_allowed_); + + if (present_queued_ && presents_allowed_) { + QueuePresentHelper(); + } +} + +} // namespace ui diff --git a/chromium/ui/ozone/platform/scenic/safe_presenter.h b/chromium/ui/ozone/platform/scenic/safe_presenter.h new file mode 100644 index 00000000000..91099573a6f --- /dev/null +++ b/chromium/ui/ozone/platform/scenic/safe_presenter.h @@ -0,0 +1,54 @@ +// 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_SCENIC_SAFE_PRESENTER_H_ +#define UI_OZONE_PLATFORM_SCENIC_SAFE_PRESENTER_H_ + +#include + +#include + +namespace ui { + +using QueuePresentCallback = fit::function; + +// Helper class used to call Present2() in fuchsia.ui.scenic.Session. By +// limiting the number of Present2 calls, SafePresenter ensures that the Session +// will not be shut down, thus, users of SafePresenter should not call Present2 +// on their own. +// +// More information can be found in the fuchsia.scenic.scheduling FIDL library, +// in the prediction_info.fidl file. +class SafePresenter { + public: + explicit SafePresenter(scenic::Session* session); + ~SafePresenter(); + + SafePresenter(const SafePresenter&) = delete; + SafePresenter& operator=(const SafePresenter&) = delete; + + // If possible, QueuePresent() immediately presents to the underlying Session. + // If the maximum amount of pending Present2()s has been reached, + // SafePresenter presents at the next earliest possible time. QueuePresent() + // ensures that callbacks get processed in FIFO order. + void QueuePresent(); + + private: + void QueuePresentHelper(); + void OnFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info); + + scenic::Session* const session_ = nullptr; + + // |presents_allowed_| is true if Scenic allows at least one more Present2() + // call. Scenic ensures a session will have a Present2 budget of at least 1 to + // begin with. + bool presents_allowed_ = true; + + // |present_queued_| is true if there are unhandled QueuePresent() calls. + bool present_queued_ = false; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_SCENIC_SAFE_PRESENTER_H_ diff --git a/chromium/ui/ozone/platform/scenic/scenic_overlay_view.cc b/chromium/ui/ozone/platform/scenic/scenic_overlay_view.cc index f7e30451b70..e3c46bd375b 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_overlay_view.cc +++ b/chromium/ui/ozone/platform/scenic/scenic_overlay_view.cc @@ -32,6 +32,7 @@ ScenicOverlayView::ScenicOverlayView( scenic::SessionPtrAndListenerRequest session_and_listener_request, ScenicSurfaceFactory* scenic_surface_factory) : scenic_session_(std::move(session_and_listener_request)), + safe_presenter_(&scenic_session_), scenic_surface_factory_(scenic_surface_factory), view_(&scenic_session_, CreateViewToken(&view_holder_token_), @@ -76,10 +77,7 @@ void ScenicOverlayView::Initialize( view_.AddChild(shape); scenic_session_.ReleaseResource(image_pipe_id); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); // Since there is one ImagePipe for each BufferCollection, it is ok to use a // fixed buffer_collection_id. @@ -123,10 +121,7 @@ void ScenicOverlayView::SetBlendMode(bool enable_blend) { // Setting alpha as |255| marks the image as opaque and no content below would // be seen. Anything lower than 255 allows blending. image_material_->SetColor(255, 255, 255, enable_blend ? 254 : 255); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); } bool ScenicOverlayView::CanAttachToAcceleratedWidget( diff --git a/chromium/ui/ozone/platform/scenic/scenic_overlay_view.h b/chromium/ui/ozone/platform/scenic/scenic_overlay_view.h index c2c25b4c0f5..0eb667ec023 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_overlay_view.h +++ b/chromium/ui/ozone/platform/scenic/scenic_overlay_view.h @@ -12,6 +12,7 @@ #include "base/threading/thread_checker.h" #include "ui/gfx/geometry/size.h" +#include "ui/ozone/platform/scenic/safe_presenter.h" #include "ui/ozone/platform/scenic/scenic_surface.h" namespace ui { @@ -60,6 +61,8 @@ class ScenicOverlayView { private: scenic::Session scenic_session_; + // Used for safely queueing Present() operations on |scenic_session_|. + SafePresenter safe_presenter_; ScenicSurfaceFactory* const scenic_surface_factory_; fuchsia::ui::views::ViewHolderToken view_holder_token_; scenic::View view_; diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface.cc b/chromium/ui/ozone/platform/scenic/scenic_surface.cc index d8ea5ddc699..25323bcb337 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_surface.cc +++ b/chromium/ui/ozone/platform/scenic/scenic_surface.cc @@ -49,6 +49,7 @@ ScenicSurface::ScenicSurface( gfx::AcceleratedWidget window, scenic::SessionPtrAndListenerRequest sesion_and_listener_request) : scenic_session_(std::move(sesion_and_listener_request)), + safe_presenter_(&scenic_session_), main_shape_(&scenic_session_), main_material_(&scenic_session_), scenic_surface_factory_(scenic_surface_factory), @@ -104,10 +105,7 @@ bool ScenicSurface::SetTextureToNewImagePipe( main_material_.SetTexture(image_pipe_id); main_shape_.SetMaterial(main_material_); scenic_session_.ReleaseResource(image_pipe_id); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); return true; } @@ -132,10 +130,7 @@ bool ScenicSurface::PresentOverlayView( entity_node.AddChild(view_holder); parent_->AddChild(entity_node); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); DCHECK(!overlays_.count(id)); overlays_.emplace( @@ -184,10 +179,7 @@ bool ScenicSurface::RemoveOverlayView(gfx::SysmemBufferCollectionId id) { auto it = overlays_.find(id); DCHECK(it != overlays_.end()); parent_->DetachChild(it->second.entity_node); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); overlays_.erase(it); return true; } @@ -203,10 +195,7 @@ mojo::PlatformHandle ScenicSurface::CreateView() { &scenic_session_, std::move(tokens.view_token), "chromium surface"); parent_->AddChild(main_shape_); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + // Defer first Present call to SetTextureToNewImagePipe(). return mojo::PlatformHandle(std::move(tokens.view_holder_token.value)); } @@ -274,10 +263,7 @@ void ScenicSurface::UpdateViewHolderScene() { main_material_.SetColor(255, 255, 255, 0 > min_z_order ? 254 : 255); main_shape_.SetTranslation(0.f, 0.f, min_z_order * kElevationStep); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); } } // namespace ui diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface.h b/chromium/ui/ozone/platform/scenic/scenic_surface.h index 148074adcdc..419d16f9a60 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_surface.h +++ b/chromium/ui/ozone/platform/scenic/scenic_surface.h @@ -18,6 +18,7 @@ #include "ui/gfx/native_pixmap_handle.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/overlay_transform.h" +#include "ui/ozone/platform/scenic/safe_presenter.h" #include "ui/ozone/public/platform_window_surface.h" namespace ui { @@ -80,12 +81,20 @@ class ScenicSurface : public ui::PlatformWindowSurface { return &scenic_session_; } + SafePresenter* safe_presenter() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return &safe_presenter_; + } + private: void UpdateViewHolderScene(); scenic::Session scenic_session_; std::unique_ptr parent_; + // Used for safely queueing Present() operations on |scenic_session_|. + SafePresenter safe_presenter_; + // Scenic resources used for the primary plane, that is not an overlay. scenic::ShapeNode main_shape_; scenic::Material main_material_; diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc index f9066115081..06e5f116d9d 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc +++ b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc @@ -119,7 +119,8 @@ class GLOzoneEGLScenic : public GLOzoneEGL { } protected: - bool LoadGLES2Bindings(gl::GLImplementation implementation) override { + bool LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) override { return LoadDefaultEGLGLES2Bindings(implementation); } @@ -183,8 +184,9 @@ ScenicSurfaceFactory::GetAllowedGLImplementations() { }; } -GLOzone* ScenicSurfaceFactory::GetGLOzone(gl::GLImplementation implementation) { - switch (implementation) { +GLOzone* ScenicSurfaceFactory::GetGLOzone( + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationSwiftShaderGL: case gl::kGLImplementationEGLGLES2: case gl::kGLImplementationEGLANGLE: diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h index 20f7dca7608..aed23be862c 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h +++ b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h @@ -43,7 +43,7 @@ class ScenicSurfaceFactory : public SurfaceFactoryOzone { // SurfaceFactoryOzone implementation. std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; std::unique_ptr CreatePlatformWindowSurface( gfx::AcceleratedWidget widget) override; std::unique_ptr CreateCanvasForWidget( diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.cc b/chromium/ui/ozone/platform/scenic/scenic_window.cc index b25ec452a2b..125e40dd99f 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_window.cc +++ b/chromium/ui/ozone/platform/scenic/scenic_window.cc @@ -5,6 +5,7 @@ #include "ui/ozone/platform/scenic/scenic_window.h" #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include "base/fuchsia/fuchsia_logging.h" +#include "base/fuchsia/process_context.h" #include "ui/events/event.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_code_conversion.h" @@ -28,7 +30,11 @@ ScenicWindow::ScenicWindow(ScenicWindowManager* window_manager, delegate_(delegate), window_id_(manager_->AddWindow(this)), event_dispatcher_(this), + keyboard_service_(base::ComponentContextForProcess() + ->svc() + ->Connect()), scenic_session_(manager_->GetScenic()), + safe_presenter_(&scenic_session_), view_ref_(std::move(properties.view_ref_pair.view_ref)), view_(&scenic_session_, std::move(std::move(properties.view_token)), @@ -55,6 +61,12 @@ ScenicWindow::ScenicWindow(ScenicWindowManager* window_manager, node_.AddChild(render_node_); delegate_->OnAcceleratedWidgetAvailable(window_id_); + + keyboard_service_.set_error_handler([](zx_status_t status) { + ZX_LOG(ERROR, status) << "input3.Keyboard service disconnected."; + }); + keyboard_client_ = std::make_unique(keyboard_service_.get(), + CloneViewRef(), this); } ScenicWindow::~ScenicWindow() { @@ -78,10 +90,7 @@ void ScenicWindow::AttachSurfaceView( render_node_.DetachChildren(); render_node_.AddChild(*surface_view_holder_); - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); } gfx::Rect ScenicWindow::GetBounds() const { @@ -93,7 +102,7 @@ void ScenicWindow::SetBounds(const gfx::Rect& bounds) { bounds_ = bounds; } -void ScenicWindow::SetTitle(const base::string16& title) { +void ScenicWindow::SetTitle(const std::u16string& title) { NOTIMPLEMENTED(); } @@ -107,10 +116,7 @@ void ScenicWindow::Show(bool inactive) { // Call Present2() to ensure that the scenic session commands are processed, // which is necessary to receive metrics event from Scenic. - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); } void ScenicWindow::Hide() { @@ -215,8 +221,16 @@ void ScenicWindow::SizeConstraintsChanged() { } void ScenicWindow::UpdateSize() { - gfx::SizeF scaled = ScaleSize(size_dips_, device_pixel_ratio_); - bounds_ = gfx::Rect(gfx::Size(ceilf(scaled.width()), ceilf(scaled.height()))); + DCHECK_GT(device_pixel_ratio_, 0.0); + DCHECK(view_properties_); + + const float width = view_properties_->bounding_box.max.x - + view_properties_->bounding_box.min.x; + const float height = view_properties_->bounding_box.max.y - + view_properties_->bounding_box.min.y; + + bounds_ = gfx::Rect(ceilf(width * device_pixel_ratio_), + ceilf(height * device_pixel_ratio_)); // Update this window's Screen's dimensions to match the new size. ScenicScreen* screen = manager_->screen(); @@ -225,25 +239,24 @@ void ScenicWindow::UpdateSize() { // Translate the node by half of the view dimensions to put it in the center // of the view. - node_.SetTranslation(size_dips_.width() / 2.0, size_dips_.height() / 2.0, - 0.f); + node_.SetTranslation(width / 2.0, height / 2.0, 0.f); // Scale the render node so that surface rect can always be 1x1. - render_node_.SetScale(size_dips_.width(), size_dips_.height(), 1.f); + render_node_.SetScale(width, height, 1.f); // Resize input node to cover the whole surface. - scenic::Rectangle window_rect(&scenic_session_, size_dips_.width(), - size_dips_.height()); + scenic::Rectangle window_rect(&scenic_session_, width, height); input_node_.SetShape(window_rect); // This is necessary when using vulkan because ImagePipes are presented // separately and we need to make sure our sizes change is committed. - scenic_session_.Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + safe_presenter_.QueuePresent(); - delegate_->OnBoundsChanged(bounds_); + PlatformWindowDelegate::BoundsChange bounds; + bounds.bounds = bounds_; + bounds.system_ui_overlap = + ConvertInsets(device_pixel_ratio_, *view_properties_); + delegate_->OnBoundsChanged(bounds); } fuchsia::ui::views::ViewRef ScenicWindow::CloneViewRef() { @@ -301,18 +314,13 @@ void ScenicWindow::OnViewMetrics(const fuchsia::ui::gfx::Metrics& metrics) { if (screen) screen->OnWindowMetrics(window_id_, device_pixel_ratio_); - if (!size_dips_.IsEmpty()) + if (view_properties_) UpdateSize(); } void ScenicWindow::OnViewProperties( const fuchsia::ui::gfx::ViewProperties& properties) { - float width = properties.bounding_box.max.x - properties.bounding_box.min.x - - properties.inset_from_min.x - properties.inset_from_max.x; - float height = properties.bounding_box.max.y - properties.bounding_box.min.y - - properties.inset_from_min.y - properties.inset_from_max.y; - - size_dips_.SetSize(width, height); + view_properties_ = properties; if (device_pixel_ratio_ > 0.0) UpdateSize(); } @@ -343,4 +351,14 @@ void ScenicWindow::DispatchEvent(ui::Event* event) { delegate_->DispatchEvent(event); } +// static +gfx::Insets ScenicWindow::ConvertInsets( + float device_pixel_ratio, + const fuchsia::ui::gfx::ViewProperties& view_properties) { + return gfx::Insets(device_pixel_ratio * view_properties.inset_from_min.y, + device_pixel_ratio * view_properties.inset_from_min.x, + device_pixel_ratio * view_properties.inset_from_max.y, + device_pixel_ratio * view_properties.inset_from_max.x); +} + } // namespace ui diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.h b/chromium/ui/ozone/platform/scenic/scenic_window.h index 3bf566cdca0..e2ff6ed51e7 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_window.h +++ b/chromium/ui/ozone/platform/scenic/scenic_window.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -16,12 +17,14 @@ #include "base/component_export.h" #include "base/macros.h" +#include "ui/base/ime/fuchsia/keyboard_client.h" #include "ui/events/fuchsia/input_event_dispatcher.h" -#include "ui/events/fuchsia/input_event_dispatcher_delegate.h" +#include "ui/events/fuchsia/input_event_sink.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/native_widget_types.h" +#include "ui/ozone/platform/scenic/safe_presenter.h" #include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/platform_window_init_properties.h" @@ -30,9 +33,8 @@ namespace ui { class ScenicWindowManager; -class COMPONENT_EXPORT(OZONE) ScenicWindow - : public PlatformWindow, - public InputEventDispatcherDelegate { +class COMPONENT_EXPORT(OZONE) ScenicWindow : public PlatformWindow, + public InputEventSink { public: // Both |window_manager| and |delegate| must outlive the ScenicWindow. // |view_token| is passed to Scenic to attach the view to the view tree. @@ -43,6 +45,13 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow PlatformWindowInitProperties properties); ~ScenicWindow() override; + // Converts Scenic's rect-based representation of insets to gfx::Insets. + // Returns zero-width insets if |inset_from_min| and |inset_from_max| are + // uninitialized (indicating that no insets were provided from Scenic). + static gfx::Insets ConvertInsets( + float device_pixel_ratio, + const fuchsia::ui::gfx::ViewProperties& view_properties); + scenic::Session* scenic_session() { return &scenic_session_; } // Embeds the View identified by |token| into the render node, @@ -55,7 +64,7 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow // PlatformWindow implementation. gfx::Rect GetBounds() const override; void SetBounds(const gfx::Rect& bounds) override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void Show(bool inactive) override; void Hide() override; void Close() override; @@ -95,7 +104,7 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow // Called from OnScenicEvents() to handle input events. void OnInputEvent(const fuchsia::ui::input::InputEvent& event); - // InputEventDispatcher::Delegate interface. + // InputEventSink implementation. void DispatchEvent(ui::Event* event) override; void UpdateSize(); @@ -107,9 +116,15 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow // Dispatches Scenic input events as Chrome ui::Events. InputEventDispatcher event_dispatcher_; + fuchsia::ui::input3::KeyboardPtr keyboard_service_; + std::unique_ptr keyboard_client_; + // Scenic session used for all drawing operations in this View. scenic::Session scenic_session_; + // Used for safely queueing Present() operations on |scenic_session_|. + SafePresenter safe_presenter_; + // Handle to a kernel object which identifies this window's View // across the system. ViewRef consumers can access the handle by // calling CloneViewRef(). @@ -142,6 +157,8 @@ class COMPONENT_EXPORT(OZONE) ScenicWindow // corresponding Scenic view. gfx::Rect bounds_; + base::Optional view_properties_; + bool visible_ = false; DISALLOW_COPY_AND_ASSIGN(ScenicWindow); diff --git a/chromium/ui/ozone/platform/scenic/scenic_window_canvas.cc b/chromium/ui/ozone/platform/scenic/scenic_window_canvas.cc index cfa7be67903..01dedec6069 100644 --- a/chromium/ui/ozone/platform/scenic/scenic_window_canvas.cc +++ b/chromium/ui/ozone/platform/scenic/scenic_window_canvas.cc @@ -166,10 +166,7 @@ void ScenicWindowCanvas::PresentCanvas(const gfx::Rect& damage) { ZX_CHECK(status == ZX_OK, status); scenic_surface_->scenic_session()->EnqueueReleaseFence( std::move(release_fence_dup)); - scenic_surface_->scenic_session()->Present2( - /*requested_presentation_time=*/0, - /*requested_prediction_span=*/0, - [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {}); + scenic_surface_->safe_presenter()->QueuePresent(); // Move to the next buffer. current_frame_ = (current_frame_ + 1) % kNumBuffers; diff --git a/chromium/ui/ozone/platform/scenic/scenic_window_unittest.cc b/chromium/ui/ozone/platform/scenic/scenic_window_unittest.cc new file mode 100644 index 00000000000..f9c59c8611b --- /dev/null +++ b/chromium/ui/ozone/platform/scenic/scenic_window_unittest.cc @@ -0,0 +1,81 @@ +// 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/scenic/scenic_window.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using fuchsia::ui::gfx::vec3; +using gfx::Insets; + +namespace ui { +namespace { + +constexpr float kDevicePixelRatio = 10.0; + +fuchsia::ui::gfx::ViewProperties CreateViewProperties(const vec3& inset_min, + const vec3& inset_max) { + fuchsia::ui::gfx::ViewProperties output; + output.inset_from_min = inset_min; + output.inset_from_max = inset_max; + return output; +} + +TEST(ScenicInsets, InsetsNotSet) { + EXPECT_EQ(ScenicWindow::ConvertInsets(kDevicePixelRatio, + CreateViewProperties({0, 0}, {0, 0})), + Insets(0, 0, 0, 0)); +} + +TEST(ScenicInsets, SingleBorder) { + // Top-aligned. + EXPECT_EQ(ScenicWindow::ConvertInsets(kDevicePixelRatio, + CreateViewProperties({0, 50}, {0, 0})), + Insets(500, 0, 0, 0)); + + // Left-aligned. + EXPECT_EQ(ScenicWindow::ConvertInsets(kDevicePixelRatio, + CreateViewProperties({50, 0}, {0, 0})), + Insets(0, 500, 0, 0)); + + // Right-aligned. + EXPECT_EQ(ScenicWindow::ConvertInsets(kDevicePixelRatio, + CreateViewProperties({0, 0}, {50, 0})), + Insets(0, 0, 0, 500)); + + // Bottom-aligned. + EXPECT_EQ(ScenicWindow::ConvertInsets(kDevicePixelRatio, + CreateViewProperties({0, 0}, {0, 50})), + Insets(0, 0, 500, 0)); +} + +TEST(ScenicInsets, Combinations) { + // All but top. + EXPECT_EQ(ScenicWindow::ConvertInsets( + kDevicePixelRatio, CreateViewProperties({50, 0}, {150, 50})), + Insets(0, 500, 500, 1500)); + + // All but left. + EXPECT_EQ(ScenicWindow::ConvertInsets( + kDevicePixelRatio, CreateViewProperties({0, 50}, {150, 50})), + Insets(500, 0, 500, 1500)); + + // All but right. + EXPECT_EQ(ScenicWindow::ConvertInsets( + kDevicePixelRatio, CreateViewProperties({50, 50}, {0, 50})), + Insets(500, 500, 500, 0)); + + // All but bottom. + EXPECT_EQ(ScenicWindow::ConvertInsets( + kDevicePixelRatio, CreateViewProperties({50, 50}, {150, 0})), + Insets(500, 500, 0, 1500)); + + // Surrounded on all sides. + EXPECT_EQ(ScenicWindow::ConvertInsets( + kDevicePixelRatio, CreateViewProperties({50, 50}, {150, 50})), + Insets(500, 500, 500, 1500)); +} + +} // namespace +} // namespace ui diff --git a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc index 6a3dee239f9..61741b67acd 100644 --- a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc +++ b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc @@ -259,8 +259,12 @@ bool SysmemBufferCollection::CreateVkImage( properties.memoryTypeBits & requirements.memoryTypeBits; uint32_t memory_type = base::bits::CountTrailingZeroBits(viable_memory_types); + VkMemoryDedicatedAllocateInfoKHR dedicated_allocate = { + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR}; + dedicated_allocate.image = *vk_image; VkImportMemoryBufferCollectionFUCHSIA buffer_collection_info = { - VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA}; + VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA, + &dedicated_allocate}; buffer_collection_info.collection = vk_buffer_collection_; buffer_collection_info.index = buffer_index; diff --git a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc index 54a822aaffc..83a4793df22 100644 --- a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc +++ b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc @@ -129,6 +129,7 @@ VulkanImplementationScenic::GetRequiredDeviceExtensions() { VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, + VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, @@ -186,7 +187,7 @@ VkSemaphore VulkanImplementationScenic::ImportSemaphoreHandle( import.semaphore = semaphore; import.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA; - import.handle = event.get(); + import.zirconHandle = event.get(); result = vkImportSemaphoreZirconHandleFUCHSIA(vk_device, &import); if (result != VK_SUCCESS) { diff --git a/chromium/ui/ozone/platform/wayland/BUILD.gn b/chromium/ui/ozone/platform/wayland/BUILD.gn index d1aab09a3a6..578e7a50ab6 100644 --- a/chromium/ui/ozone/platform/wayland/BUILD.gn +++ b/chromium/ui/ozone/platform/wayland/BUILD.gn @@ -12,6 +12,8 @@ import("//testing/libfuzzer/fuzzer_test.gni") import("//third_party/wayland/features.gni") import("//ui/ozone/platform/wayland/wayland.gni") +assert(is_linux || is_chromeos_lacros) + source_set("wayland") { sources = [ "client_native_pixmap_factory_wayland.cc", @@ -194,9 +196,11 @@ source_set("wayland") { "//ui/base/cursor:cursor_base", "//ui/base/cursor:theme_manager", "//ui/base/cursor/mojom:cursor_type", + "//ui/base/dragdrop:types", "//ui/base/ime/linux", "//ui/events", "//ui/events:dom_keycode_converter", + "//ui/events/devices", "//ui/events/keycodes:xkb", "//ui/events/ozone", "//ui/events/ozone/evdev", @@ -210,21 +214,18 @@ source_set("wayland") { "//ui/ozone/common", "//ui/ozone/public/mojom/wayland:wayland_mojom", "//ui/platform_window", + "//ui/platform_window/common", "//ui/platform_window/wm", ] - if (is_linux || is_chromeos_lacros) { - deps += [ "//ui/base/ime/linux" ] - } - if (use_gtk) { sources += [ "host/gtk_ui_delegate_wayland.cc", "host/gtk_ui_delegate_wayland.h", ] deps += [ - "//build/config/linux/gtk", "//ui/gtk:gtk_ui_delegate", + "//ui/gtk/wayland", ] } @@ -279,6 +280,14 @@ source_set("wayland") { deps += [ "//gpu/vulkan" ] } + # Proxy implementation that is used by input emulation. + sources += [ + "host/proxy/wayland_proxy_impl.cc", + "host/proxy/wayland_proxy_impl.h", + ] + + deps += [ ":wayland_proxy" ] + configs += [ "//third_party/khronos:khronos_headers" ] } @@ -409,6 +418,7 @@ source_set("wayland_unittests") { "//ui/base", "//ui/base:buildflags", "//ui/base/cursor", + "//ui/base/dragdrop:types", "//ui/base/ime/linux", "//ui/events/ozone/layout", "//ui/gfx/linux:test_support", @@ -453,3 +463,48 @@ fuzzer_test("wayland_buffer_fuzzer") { "//ui/platform_window:platform_window", ] } + +source_set("ui_test_support") { + testonly = true + sources = [ + "emulate/wayland_input_emulate.cc", + "emulate/wayland_input_emulate.h", + "test/wayland_ozone_ui_controls_test_helper.cc", + "test/wayland_ozone_ui_controls_test_helper.h", + ] + + deps = [ + ":wayland_proxy", + "//base", + "//third_party/wayland-protocols:weston_test", + "//ui/base:test_support", + "//ui/events", + "//ui/events:dom_keycode_converter", + "//ui/events:test_support", + "//ui/events/types:headers", + "//ui/gfx", + "//ui/platform_window/common", + ] +} + +component("wayland_proxy") { + visibility = [] + visibility += [ + ":ui_test_support", + ":wayland", + ] + + sources = [ + "host/proxy/wayland_proxy.cc", + "host/proxy/wayland_proxy.h", + ] + + defines = [ "IS_WAYLAND_PROXY_IMPL" ] + + deps = [ + "//base", + "//ui/gfx", + "//ui/platform_window", + "//ui/platform_window/common", + ] +} diff --git a/chromium/ui/ozone/platform/wayland/DEPS b/chromium/ui/ozone/platform/wayland/DEPS index b7393cb1394..a035c9180a4 100644 --- a/chromium/ui/ozone/platform/wayland/DEPS +++ b/chromium/ui/ozone/platform/wayland/DEPS @@ -3,6 +3,7 @@ include_rules = [ "+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", diff --git a/chromium/ui/ozone/platform/wayland/common/data_util.cc b/chromium/ui/ozone/platform/wayland/common/data_util.cc index 94c84236a2c..21a372f1f9a 100644 --- a/chromium/ui/ozone/platform/wayland/common/data_util.cc +++ b/chromium/ui/ozone/platform/wayland/common/data_util.cc @@ -4,11 +4,11 @@ #include "ui/ozone/platform/wayland/common/data_util.h" +#include #include #include "base/check.h" #include "base/logging.h" -#include "base/strings/string16.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/clipboard/clipboard_constants.h" @@ -101,7 +101,7 @@ void AddFiles(PlatformClipboard::Data data, OSExchangeData* os_exchange_data) { } std::string url_path = url.path(); - url::RawCanonOutputT unescaped; + url::RawCanonOutputT unescaped; url::DecodeURLEscapeSequences(url_path.data(), url_path.size(), url::DecodeURLMode::kUTF8OrIsomorphic, &unescaped); @@ -127,11 +127,11 @@ void AddUrl(PlatformClipboard::Data data, OSExchangeData* os_exchange_data) { if (data->data().empty()) return; - base::string16 data_as_string16 = BytesTo(data); + std::u16string data_as_string16 = BytesTo(data); const auto lines = - base::SplitString(data_as_string16, base::ASCIIToUTF16("\r\n"), - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + base::SplitString(data_as_string16, u"\r\n", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); if (lines.size() != 2U) { LOG(WARNING) << "Invalid data passed as text/x-moz-url; it must contain " << "exactly 2 lines but has " << lines.size() << " instead."; @@ -191,20 +191,20 @@ bool ExtractOSExchangeData(const OSExchangeData& exchange_data, if (mime_type == ui::kMimeTypeMozillaURL && exchange_data.HasURL(kFilenameToURLPolicy)) { GURL url; - base::string16 title; + std::u16string title; exchange_data.GetURLAndTitle(kFilenameToURLPolicy, &url, &title); out_content->append(url.spec()); return true; } if (mime_type == ui::kMimeTypeHTML && exchange_data.HasHtml()) { - base::string16 data; + std::u16string data; GURL base_url; exchange_data.GetHtml(&data, &base_url); out_content->append(base::UTF16ToUTF8(data)); return true; } if (exchange_data.HasString()) { - base::string16 data; + std::u16string data; exchange_data.GetString(&data); out_content->append(base::UTF16ToUTF8(data)); return true; diff --git a/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc b/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc new file mode 100644 index 00000000000..bc939e793ca --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.cc @@ -0,0 +1,363 @@ +// 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/emulate/wayland_input_emulate.h" + +#include +#include +#include + +#include + +#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" + +namespace wl { + +WaylandInputEmulate::PendingEvent::PendingEvent( + ui::EventType event_type, + gfx::AcceleratedWidget target_widget) + : type(event_type), widget(target_widget) { + DCHECK(type == ui::EventType::ET_MOUSE_MOVED || + type == ui::EventType::ET_MOUSE_PRESSED || + type == ui::EventType::ET_MOUSE_RELEASED || + type == ui::EventType::ET_KEY_PRESSED || + type == ui::EventType::ET_KEY_RELEASED); +} + +WaylandInputEmulate::PendingEvent::~PendingEvent() = default; + +WaylandInputEmulate::TestWindow::TestWindow( + gfx::AcceleratedWidget target_widget, + WaylandInputEmulate* input_emulate) + : widget(target_widget), emulate(input_emulate) {} + +WaylandInputEmulate::TestWindow::~TestWindow() = default; + +WaylandInputEmulate::WaylandInputEmulate() { + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + + wayland_proxy->SetDelegate(this); + + registry_ = wl_display_get_registry(wayland_proxy->GetDisplay()); + if (!registry_) + LOG(FATAL) << "Failed to get Wayland registry"; + + static const wl_registry_listener registry_listener = { + &WaylandInputEmulate::Global}; + + wl_registry_add_listener(registry_, ®istry_listener, this); + + // Roundtrip one time to get the weston-test global. + wl_display_roundtrip(wayland_proxy->GetDisplay()); + if (!weston_test_) + LOG(FATAL) << "weston-test is not available."; + + static const struct weston_test_listener test_listener = { + &WaylandInputEmulate::HandlePointerPosition, + &WaylandInputEmulate::HandlePointerButton, + &WaylandInputEmulate::HandleKeyboardKey, + }; + weston_test_add_listener(weston_test_, &test_listener, this); +} + +WaylandInputEmulate::~WaylandInputEmulate() { + DCHECK(observers_.empty()); + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + wayland_proxy->SetDelegate(nullptr); + + weston_test_destroy(weston_test_); + wl_registry_destroy(registry_); +} + +void WaylandInputEmulate::AddObserver(Observer* obs) { + observers_.AddObserver(obs); +} + +void WaylandInputEmulate::RemoveObserver(Observer* obs) { + observers_.RemoveObserver(obs); +} + +void WaylandInputEmulate::EmulatePointerMotion(gfx::AcceleratedWidget widget, + gfx::Point mouse_surface_loc) { + auto it = windows_.find(widget); + DCHECK(it != windows_.end()); + + auto* test_window = it->second.get(); + if (!test_window->buffer_attached_and_configured) { + auto pending_event = + std::make_unique(ui::EventType::ET_MOUSE_MOVED, widget); + pending_event->pointer_surface_location_in_px = mouse_surface_loc; + test_window->pending_events.emplace_back(std::move(pending_event)); + return; + } + + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + + auto* wlsurface = wayland_proxy->GetWlSurfaceForAcceleratedWidget(widget); + + // If it's a toplevel window, activate it. This results in raising the the + // parent window and its children windows. + auto window_type = wayland_proxy->GetWindowType(widget); + if (window_type != ui::PlatformWindowType::kTooltip && + window_type != ui::PlatformWindowType::kMenu && + !wayland_proxy->WindowHasPointerFocus(widget)) { + weston_test_activate_surface(weston_test_, wlsurface); + } + + timespec ts = (base::TimeTicks::Now() - base::TimeTicks()).ToTimeSpec(); + weston_test_move_pointer(weston_test_, wlsurface, + static_cast(ts.tv_sec) >> 32, + ts.tv_sec & 0xffffffff, ts.tv_nsec, + mouse_surface_loc.x(), mouse_surface_loc.y()); + wayland_proxy->ScheduleDisplayFlush(); +} + +void WaylandInputEmulate::EmulatePointerButton(gfx::AcceleratedWidget widget, + ui::EventType event_type, + uint32_t changed_button) { + DCHECK(event_type == ui::EventType::ET_MOUSE_PRESSED || + event_type == ui::EventType::ET_MOUSE_RELEASED); + // A button press/release event uses previous location that Ozone/Wayland got + // when OnPointerMotionEvent was called. + auto it = windows_.find(widget); + DCHECK(it != windows_.end()); + + auto* test_window = it->second.get(); + if (!test_window->buffer_attached_and_configured) { + auto pending_event = std::make_unique(event_type, widget); + pending_event->mouse_button = changed_button; + test_window->pending_events.emplace_back(std::move(pending_event)); + return; + } + + DCHECK_NE(0u, changed_button); + timespec ts = (base::TimeTicks::Now() - base::TimeTicks()).ToTimeSpec(); + weston_test_send_button(weston_test_, static_cast(ts.tv_sec) >> 32, + ts.tv_sec & 0xffffffff, ts.tv_nsec, changed_button, + (event_type == ui::EventType::ET_MOUSE_PRESSED + ? WL_POINTER_BUTTON_STATE_PRESSED + : WL_POINTER_BUTTON_STATE_RELEASED)); +} + +void WaylandInputEmulate::EmulateKeyboardKey(gfx::AcceleratedWidget widget, + ui::EventType event_type, + ui::DomCode dom_code) { + DCHECK(event_type == ui::EventType::ET_KEY_PRESSED || + event_type == ui::EventType::ET_KEY_RELEASED); + + auto it = windows_.find(widget); + DCHECK(it != windows_.end()); + + auto* test_window = it->second.get(); + if (!test_window->buffer_attached_and_configured) { + auto pending_event = std::make_unique(event_type, widget); + pending_event->key_dom_code = dom_code; + test_window->pending_events.emplace_back(std::move(pending_event)); + return; + } + + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + + auto* wlsurface = wayland_proxy->GetWlSurfaceForAcceleratedWidget(widget); + + // Raise the window and set keyboard focus. + if (!wayland_proxy->WindowHasKeyboardFocus(widget)) + weston_test_activate_surface(weston_test_, wlsurface); + + timespec ts = (base::TimeTicks::Now() - base::TimeTicks()).ToTimeSpec(); + weston_test_send_key(weston_test_, static_cast(ts.tv_sec) >> 32, + ts.tv_sec & 0xffffffff, ts.tv_nsec, + ui::KeycodeConverter::DomCodeToEvdevCode(dom_code), + (event_type == ui::EventType::ET_KEY_PRESSED + ? WL_KEYBOARD_KEY_STATE_PRESSED + : WL_KEYBOARD_KEY_STATE_RELEASED)); + wayland_proxy->ScheduleDisplayFlush(); +} + +void WaylandInputEmulate::OnWindowConfigured(gfx::AcceleratedWidget widget) { + auto it = windows_.find(widget); + DCHECK(it != windows_.end()); + + auto* test_surface = it->second.get(); + if (test_surface->buffer_attached_and_configured) + return; + + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + + // Once window is configured aka xdg_toplevel/popup role is assigned, a buffer + // with correct size must be attached. Otherwise, actual size of the surface + // will be size of the last attached buffer or 0x0). + // + // This is needed as running some tests doesn't result in sending frames that + // require buffers to be created.; + auto buffer_size = wayland_proxy->GetWindowBounds(widget).size(); + DCHECK(!buffer_size.IsEmpty()); + test_surface->buffer = wayland_proxy->CreateShmBasedWlBuffer(buffer_size); + + auto* wlsurface = wayland_proxy->GetWlSurfaceForAcceleratedWidget(widget); + wl_surface_attach(wlsurface, test_surface->buffer, 0, 0); + wl_surface_damage(wlsurface, 0, 0, buffer_size.width(), buffer_size.height()); + + static const struct wl_callback_listener kFrameCallbackListener = { + &WaylandInputEmulate::FrameCallbackHandler}; + + // Setup frame callback to know when the surface is finally ready to get + // events. Otherwise, the width & height might not have been correctly set + // before the mouse events are sent. + test_surface->frame_callback = wl_surface_frame(wlsurface); + wl_callback_add_listener(test_surface->frame_callback, + &kFrameCallbackListener, this); + + wl_surface_commit(wlsurface); + + wayland_proxy->ScheduleDisplayFlush(); +} + +void WaylandInputEmulate::OnWindowRemoved(gfx::AcceleratedWidget widget) { + auto it = windows_.find(widget); + DCHECK(it != windows_.end()); + + // Destroy the frame callback. + if (it->second->frame_callback) { + wl_callback_destroy(it->second->frame_callback); + it->second->frame_callback = nullptr; + } + + // Destroy the attached buffer. + if (it->second->buffer) { + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + wayland_proxy->DestroyShmForWlBuffer(it->second->buffer); + wayland_proxy->ScheduleDisplayFlush(); + } + windows_.erase(it); +} + +void WaylandInputEmulate::OnWindowAdded(gfx::AcceleratedWidget widget) { + // It must be a first run. Thus, reset the pointer state so that the next + // tests do not inherit the previous test's clicks. Otherwise, there can be + // a button pressed state left if the previous test crashed. + if (windows_.empty()) { + weston_test_reset_pointer(weston_test_); + auto* wayland_proxy = wl::WaylandProxy::GetInstance(); + DCHECK(wayland_proxy); + wayland_proxy->ScheduleDisplayFlush(); + } + + windows_.emplace( + widget, std::make_unique(widget, this)); +} + +// static +void WaylandInputEmulate::HandlePointerPosition(void* data, + struct weston_test* weston_test, + wl_fixed_t x, + wl_fixed_t y) { + WaylandInputEmulate* emulate = static_cast(data); + auto mouse_position_on_screen_px = + gfx::Point(wl_fixed_to_int(x), wl_fixed_to_int(y)); + for (WaylandInputEmulate::Observer& observer : emulate->observers_) + observer.OnPointerMotionGlobal(mouse_position_on_screen_px); +} + +// static +void WaylandInputEmulate::HandlePointerButton(void* data, + struct weston_test* weston_test, + int32_t button, + uint32_t state) { + WaylandInputEmulate* emulate = static_cast(data); + for (WaylandInputEmulate::Observer& observer : emulate->observers_) { + observer.OnPointerButtonGlobal(button, + state == WL_POINTER_BUTTON_STATE_PRESSED); + } +} + +// static +void WaylandInputEmulate::HandleKeyboardKey(void* data, + struct weston_test* weston_test, + uint32_t key, + uint32_t state) { + WaylandInputEmulate* emulate = static_cast(data); + for (WaylandInputEmulate::Observer& observer : emulate->observers_) + observer.OnKeyboardKey(key, state == WL_KEYBOARD_KEY_STATE_PRESSED); +} + +// static +void WaylandInputEmulate::Global(void* data, + wl_registry* registry, + uint32_t name, + const char* interface, + uint32_t version) { + auto* emulate = static_cast(data); + if (strcmp(interface, "weston_test") == 0) { + const struct wl_interface* interface = + static_cast(&weston_test_interface); + emulate->weston_test_ = static_cast( + wl_registry_bind(registry, name, interface, version)); + } +} + +// static +void WaylandInputEmulate::FrameCallbackHandler(void* data, + struct wl_callback* callback, + uint32_t time) { + WaylandInputEmulate* emulate = static_cast(data); + CHECK(emulate) + << "WaylandInputEmulate was destroyed before a frame callback arrived"; + + WaylandInputEmulate::TestWindow* window = nullptr; + for (const auto& window_item : emulate->windows_) { + if (window_item.second->frame_callback == callback) { + window = window_item.second.get(); + break; + } + } + + if (!window) + return; + + wl_callback_destroy(window->frame_callback); + window->frame_callback = nullptr; + + DCHECK(!window->buffer_attached_and_configured); + window->buffer_attached_and_configured = true; + + while (!window->pending_events.empty()) { + auto event = std::move(window->pending_events.front()); + window->pending_events.pop_front(); + + auto* input_emulate = window->emulate; + DCHECK(input_emulate); + + switch (event->type) { + case ui::EventType::ET_MOUSE_MOVED: + input_emulate->EmulatePointerMotion( + window->widget, event->pointer_surface_location_in_px); + break; + case ui::EventType::ET_MOUSE_PRESSED: + case ui::EventType::ET_MOUSE_RELEASED: + input_emulate->EmulatePointerButton(window->widget, event->type, + event->mouse_button); + break; + case ui::EventType::ET_KEY_PRESSED: + case ui::EventType::ET_KEY_RELEASED: + input_emulate->EmulateKeyboardKey(window->widget, event->type, + event->key_dom_code); + break; + default: + NOTREACHED(); + break; + } + } +} + +} // namespace wl diff --git a/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h b/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h new file mode 100644 index 00000000000..d5c67ac507c --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/emulate/wayland_input_emulate.h @@ -0,0 +1,165 @@ +// 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_EMULATE_WAYLAND_INPUT_EMULATE_H_ +#define UI_OZONE_PLATFORM_WAYLAND_EMULATE_WAYLAND_INPUT_EMULATE_H_ + +#include + +#include + +#include "base/component_export.h" +#include "base/containers/circular_deque.h" +#include "base/containers/flat_map.h" +#include "base/observer_list.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/types/event_type.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/ozone/platform/wayland/host/proxy/wayland_proxy.h" + +struct wl_buffer; +struct wl_registry; +struct weston_test; +struct wl_callback; + +namespace wl { + +// Emulates Keyboard, Pointer, Touch events that ui_interactive_tests test +// suite sends. Mustn't be used in production code. +class WaylandInputEmulate : public wl::WaylandProxy::Delegate { + public: + // Notifies the observer about events sent by Wayland compositor. + class Observer : public base::CheckedObserver { + public: + virtual void OnPointerMotionGlobal(const gfx::Point& screen_position) = 0; + + // Notifies Wayland compositor has sent |button| event that corresponds to + // event codes in Linux's input-event-codes.h. + virtual void OnPointerButtonGlobal(int32_t button, bool pressed) = 0; + + // Notifies Wayland compositor has sent |key| event that corresponds to + // event codes in Linux's input-event-codes.h. + virtual void OnKeyboardKey(int32_t key, bool pressed) = 0; + + protected: + ~Observer() override = default; + }; + + WaylandInputEmulate(); + ~WaylandInputEmulate() override; + + void AddObserver(Observer* obs); + void RemoveObserver(Observer* obs); + void EmulatePointerMotion(gfx::AcceleratedWidget widget, + gfx::Point mouse_surface_loc); + void EmulatePointerButton(gfx::AcceleratedWidget widget, + ui::EventType event_type, + uint32_t changed_button); + void EmulateKeyboardKey(gfx::AcceleratedWidget widget, + ui::EventType event_type, + ui::DomCode dom_code); + + private: + // Pending emulated events. Can be ET_MOUSE_MOVED, + // ET_MOUSE_PRESSED/ET_MOUSE_RELEASED, or ET_KEY_PRESSED/ET_KEY_RELEASED. + struct PendingEvent { + PendingEvent(ui::EventType event_type, + gfx::AcceleratedWidget target_widget); + ~PendingEvent(); + + ui::EventType type; + gfx::AcceleratedWidget widget; + + // Set for type == ET_MOUSE_MOVED. + gfx::Point pointer_surface_location_in_px; + + // Set for type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED. + uint32_t mouse_button = 0; + + // Set for type == ET_KEY_PRESSED || type == ET_KEY_RELEASED. + ui::DomCode key_dom_code = ui::DomCode::NONE; + }; + + // A container that tracks created WaylandWindows and keeps some fundamental + // bits to make emulation work flawlessly. + struct TestWindow { + TestWindow(gfx::AcceleratedWidget target_widget, + WaylandInputEmulate* emulate); + ~TestWindow(); + + // Widget that this TestWindow represents. This corresponds to a + // WaylandWindow created on the Ozone/Wayland side. + gfx::AcceleratedWidget widget; + + // Non-owned pointer to input emulation. + WaylandInputEmulate* emulate = nullptr; + + // Control flag that says if the buffer has been attached and a consequent + // frame callback has been received. This is required to be able to know + // that the surface has consumed the attached buffer and Wayland properly + // set the size of the surface. Otherwise, the surface in question may not + // receive any events. Set during WaylandInputEmulate::FrameCallbackHandler + // call. + bool buffer_attached_and_configured = false; + + // Pending events to be sent for this TestWindow. These are sent after + // buffer_attached_and_configured is set to true. + base::circular_deque> pending_events; + + // Frame callback that invokes WaylandInputEmulate::FrameCallbackHandler. + struct wl_callback* frame_callback = nullptr; + + // The attached buffer. + wl_buffer* buffer = nullptr; + }; + + // WaylandProxy::Delegate. + void OnWindowAdded(gfx::AcceleratedWidget widget) override; + void OnWindowRemoved(gfx::AcceleratedWidget widget) override; + void OnWindowConfigured(gfx::AcceleratedWidget widget) override; + + // weston_test_listener. + static void HandlePointerPosition(void* data, + struct weston_test* weston_test, + wl_fixed_t x, + wl_fixed_t y); + static void HandlePointerButton(void* data, + struct weston_test* weston_test, + int32_t button, + uint32_t state); + static void HandleKeyboardKey(void* data, + struct weston_test* weston_test, + uint32_t key, + uint32_t state); + + // wl_registry_listener. + static void Global(void* data, + wl_registry* registry, + uint32_t name, + const char* interface, + uint32_t version); + + // wl_callback_listener. + static void FrameCallbackHandler(void* data, + struct wl_callback* callback, + uint32_t time); + + // Stores existing windows. + base::flat_map> + windows_; + + base::ObserverList observers_; + + // Owned raw pointers. wl::Object is not used because the component this + // class belongs to cannot depend on the "wayland" target in the + // //ui/ozone/platform/wayland/BUILD.gn + struct wl_registry* registry_ = nullptr; + struct weston_test* weston_test_ = nullptr; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_EMULATE_WAYLAND_INPUT_EMULATE_H_ 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 827cd1c9b7d..81d1fddbb71 100644 --- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc +++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc @@ -186,6 +186,10 @@ bool GbmSurfacelessWayland::SupportsOverridePlatformSize() const { return true; } +bool GbmSurfacelessWayland::SupportsViewporter() const { + return buffer_manager_->supports_viewporter(); +} + gfx::SurfaceOrigin GbmSurfacelessWayland::GetOrigin() const { // GbmSurfacelessWayland's y-axis is flipped compare to GL - (0,0) is at top // left corner. 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 8be5c32391f..2553c380b51 100644 --- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h +++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h @@ -62,6 +62,7 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL, void SetRelyOnImplicitSync() override; bool SupportsPlaneGpuFences() const override; bool SupportsOverridePlatformSize() const override; + bool SupportsViewporter() const override; gfx::SurfaceOrigin GetOrigin() const override; private: diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc index b430a061c26..12441379f58 100644 --- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc +++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc @@ -25,12 +25,15 @@ std::unique_ptr CreateWaylandEglWindow( window->root_surface()->surface(), size.width(), size.height())); } -GLSurfaceWayland::GLSurfaceWayland(WaylandEglWindowPtr egl_window) +GLSurfaceWayland::GLSurfaceWayland(WaylandEglWindowPtr egl_window, + WaylandWindow* window) : NativeViewGLSurfaceEGL( reinterpret_cast(egl_window.get()), nullptr), - egl_window_(std::move(egl_window)) { + egl_window_(std::move(egl_window)), + window_(window) { DCHECK(egl_window_); + DCHECK(window_); } bool GLSurfaceWayland::Resize(const gfx::Size& size, @@ -66,8 +69,29 @@ EGLConfig GLSurfaceWayland::GetConfig() { return config_; } +gfx::SwapResult GLSurfaceWayland::SwapBuffers(PresentationCallback callback) { + UpdateVisualSize(); + return gl::NativeViewGLSurfaceEGL::SwapBuffers(std::move(callback)); +} + +gfx::SwapResult GLSurfaceWayland::PostSubBuffer(int x, + int y, + int width, + int height, + PresentationCallback callback) { + UpdateVisualSize(); + return gl::NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height, + std::move(callback)); +} + GLSurfaceWayland::~GLSurfaceWayland() { Destroy(); } +void GLSurfaceWayland::UpdateVisualSize() { + window_->ui_task_runner()->PostTask( + FROM_HERE, base::BindOnce(&WaylandWindow::UpdateVisualSize, + base::Unretained(window_), size_)); +} + } // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.h index 87a7da0d18b..ebefad84996 100644 --- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.h +++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.h @@ -29,7 +29,7 @@ class GLSurfaceWayland : public gl::NativeViewGLSurfaceEGL { public: using WaylandEglWindowPtr = std::unique_ptr; - explicit GLSurfaceWayland(WaylandEglWindowPtr egl_window); + GLSurfaceWayland(WaylandEglWindowPtr egl_window, WaylandWindow* window); // gl::GLSurface: bool Resize(const gfx::Size& size, @@ -37,11 +37,20 @@ class GLSurfaceWayland : public gl::NativeViewGLSurfaceEGL { const gfx::ColorSpace& color_space, bool has_alpha) override; EGLConfig GetConfig() override; + gfx::SwapResult SwapBuffers(PresentationCallback callback) override; + gfx::SwapResult PostSubBuffer(int x, + int y, + int width, + int height, + PresentationCallback callback) override; private: ~GLSurfaceWayland() override; + void UpdateVisualSize(); + WaylandEglWindowPtr egl_window_; + WaylandWindow* const window_; DISALLOW_COPY_AND_ASSIGN(GLSurfaceWayland); }; 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 da7ce23565e..e1585512283 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 @@ -45,14 +45,15 @@ void WaylandBufferManagerGpu::Initialize( const base::flat_map<::gfx::BufferFormat, std::vector>& buffer_formats_with_modifiers, bool supports_dma_buf, + bool supports_viewporter, bool supports_acquire_fence) { - DCHECK(supported_buffer_formats_with_modifiers_.empty()); supported_buffer_formats_with_modifiers_ = buffer_formats_with_modifiers; #if defined(WAYLAND_GBM) if (!supports_dma_buf) set_gbm_device(nullptr); #endif + supports_viewporter_ = supports_viewporter; supports_acquire_fence_ = supports_acquire_fence; BindHostInterface(std::move(remote_host)); @@ -228,7 +229,7 @@ void WaylandBufferManagerGpu::DestroyBuffer(gfx::AcceleratedWidget widget, void WaylandBufferManagerGpu::AddBindingWaylandBufferManagerGpu( mojo::PendingReceiver receiver) { - receiver_.Bind(std::move(receiver)); + receiver_set_.Add(this, std::move(receiver)); } const std::vector& @@ -287,6 +288,12 @@ void WaylandBufferManagerGpu::DestroyBufferInternal( void WaylandBufferManagerGpu::BindHostInterface( mojo::PendingRemote remote_host) { + // WaylandBufferManagerHost may bind host again after an error. See + // WaylandBufferManagerHost::BindInterface for more details. + if (remote_host_.is_bound()) { + remote_host_.reset(); + associated_receiver_.reset(); + } remote_host_.Bind(std::move(remote_host)); // Setup associated interface. 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 8123ade0306..56579442530 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 @@ -51,6 +51,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { const base::flat_map<::gfx::BufferFormat, std::vector>& buffer_formats_with_modifiers, bool supports_dma_buf, + bool supports_viewporter, bool supports_acquire_fence) override; // These two calls get the surface, which backs the |widget| and notifies it @@ -128,6 +129,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { #endif bool supports_acquire_fence() const { return supports_acquire_fence_; } + bool supports_viewporter() const { return supports_viewporter_; } // Adds a WaylandBufferManagerGpu binding. void AddBindingWaylandBufferManagerGpu( @@ -183,7 +185,11 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu { // Whether Wayland server allows buffer submission with acquire fence. bool supports_acquire_fence_ = false; - mojo::Receiver receiver_{this}; + // Whether Wayland server implements wp_viewporter extension to support + // cropping and scaling buffers. + bool supports_viewporter_ = false; + + mojo::ReceiverSet receiver_set_; // A pointer to a WaylandBufferManagerHost object, which always lives on a // browser process side. It's used for a multi-process mode. 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 18f555b2076..69d54932edd 100644 --- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc +++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc @@ -51,7 +51,7 @@ class GLOzoneEGLWayland : public GLOzoneEGL { protected: gl::EGLDisplayPlatform GetNativeDisplay() override; - bool LoadGLES2Bindings(gl::GLImplementation impl) override; + bool LoadGLES2Bindings(const gl::GLImplementationParts& impl) override; private: WaylandConnection* const connection_; @@ -77,12 +77,13 @@ scoped_refptr GLOzoneEGLWayland::CreateViewGLSurface( auto egl_window = CreateWaylandEglWindow(window); if (!egl_window) return nullptr; - return gl::InitializeGLSurface(new GLSurfaceWayland(std::move(egl_window))); + return gl::InitializeGLSurface( + new GLSurfaceWayland(std::move(egl_window), window)); } scoped_refptr GLOzoneEGLWayland::CreateSurfacelessViewGLSurface( gfx::AcceleratedWidget window) { - if (gl::GetGLImplementation() == gl::kGLImplementationSwiftShaderGL) { + if (gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) { return gl::InitializeGLSurface( base::MakeRefCounted(window, buffer_manager_)); @@ -116,7 +117,8 @@ gl::EGLDisplayPlatform GLOzoneEGLWayland::GetNativeDisplay() { return gl::EGLDisplayPlatform(EGL_DEFAULT_DISPLAY); } -bool GLOzoneEGLWayland::LoadGLES2Bindings(gl::GLImplementation impl) { +bool GLOzoneEGLWayland::LoadGLES2Bindings( + const gl::GLImplementationParts& impl) { // TODO: It may not be necessary to set this environment variable when using // swiftshader. setenv("EGL_PLATFORM", "wayland", 0); @@ -151,8 +153,8 @@ WaylandSurfaceFactory::GetAllowedGLImplementations() { } GLOzone* WaylandSurfaceFactory::GetGLOzone( - gl::GLImplementation implementation) { - switch (implementation) { + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationEGLGLES2: case gl::kGLImplementationSwiftShaderGL: return egl_implementation_.get(); 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 18a0319c1d9..a20e8094d39 100644 --- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h +++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h @@ -28,7 +28,7 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone { // SurfaceFactoryOzone overrides: std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; #if BUILDFLAG(ENABLE_VULKAN) std::unique_ptr CreateVulkanImplementation( bool use_swiftshader, 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 310d4a9be16..64331f786e7 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 @@ -178,7 +178,8 @@ class WaylandSurfaceFactoryTest : public WaylandTest { WaylandTest::SetUp(); auto manager_ptr = connection_->buffer_manager_host()->BindInterface(); - buffer_manager_gpu_->Initialize(std::move(manager_ptr), {}, false, false); + buffer_manager_gpu_->Initialize(std::move(manager_ptr), {}, false, true, + false); // Wait until initialization and mojo calls go through. base::RunLoop().RunUntilIdle(); @@ -213,7 +214,8 @@ TEST_P(WaylandSurfaceFactoryTest, buffer_manager_gpu_->set_gbm_device(std::make_unique()); - auto* gl_ozone = surface_factory_->GetGLOzone(gl::kGLImplementationEGLGLES2); + auto* gl_ozone = surface_factory_->GetGLOzone( + gl::GLImplementationParts(gl::kGLImplementationEGLGLES2)); auto gl_surface = gl_ozone->CreateSurfacelessViewGLSurface(widget_); EXPECT_TRUE(gl_surface); gl_surface->SetRelyOnImplicitSync(); @@ -462,7 +464,8 @@ TEST_P(WaylandSurfaceFactoryTest, buffer_manager_gpu_->set_gbm_device(std::make_unique()); - auto* gl_ozone = surface_factory_->GetGLOzone(gl::kGLImplementationEGLGLES2); + auto* gl_ozone = surface_factory_->GetGLOzone( + gl::GLImplementationParts(gl::kGLImplementationEGLGLES2)); auto gl_surface = gl_ozone->CreateSurfacelessViewGLSurface(widget_); EXPECT_TRUE(gl_surface); gl_surface->SetRelyOnImplicitSync(); @@ -754,7 +757,8 @@ TEST_P(WaylandSurfaceFactoryTest, CreateSurfaceCheckGbm) { // used. EXPECT_FALSE(buffer_manager_gpu_->gbm_device()); - auto* gl_ozone = surface_factory_->GetGLOzone(gl::kGLImplementationEGLGLES2); + auto* gl_ozone = surface_factory_->GetGLOzone( + gl::GLImplementationParts(gl::kGLImplementationEGLGLES2)); EXPECT_TRUE(gl_ozone); auto gl_surface = gl_ozone->CreateSurfacelessViewGLSurface(widget_); EXPECT_FALSE(gl_surface); diff --git a/chromium/ui/ozone/platform/wayland/host/DEPS b/chromium/ui/ozone/platform/wayland/host/DEPS index b9371fab272..c23eb538519 100644 --- a/chromium/ui/ozone/platform/wayland/host/DEPS +++ b/chromium/ui/ozone/platform/wayland/host/DEPS @@ -4,4 +4,6 @@ include_rules = [ "+chromeos/crosapi/cpp/crosapi_constants.h", "+chromeos/lacros/lacros_chrome_service_impl.h", "+chromeos/ui/base", + # Common includes. + "+ui/base/linux/linux_desktop.h", ] diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc b/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc index cb501cbd8f0..20bb8662233 100644 --- a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc +++ b/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.cc @@ -4,14 +4,9 @@ #include "ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h" -#include +#include -#include - -#include "base/bind.h" -#include "base/environment.h" #include "base/logging.h" -#include "ui/gfx/native_widget_types.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" @@ -20,56 +15,18 @@ #include "ui/ozone/platform/wayland/host/xdg_foreign_wrapper.h" #include "ui/platform_window/platform_window_init_properties.h" -#if GTK_CHECK_VERSION(3, 90, 0) -#include -#else -#include - -#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 { GtkUiDelegateWayland::GtkUiDelegateWayland(WaylandConnection* connection) : connection_(connection) { DCHECK(connection_); - 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"); } GtkUiDelegateWayland::~GtkUiDelegateWayland() = default; -void GtkUiDelegateWayland::OnInitialized() { - // Nothing to do upon initialization for Wayland. -} - -GdkKeymap* GtkUiDelegateWayland::GetGdkKeymap() { - NOTIMPLEMENTED_LOG_ONCE(); - return nullptr; -} - -GdkWindow* GtkUiDelegateWayland::GetGdkWindow( - gfx::AcceleratedWidget window_id) { - NOTIMPLEMENTED_LOG_ONCE(); - return nullptr; -} - -bool GtkUiDelegateWayland::SetGdkWindowTransientFor( - GdkWindow* window, - gfx::AcceleratedWidget parent) { -#if !GTK_CHECK_VERSION(3, 90, 0) - 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 - +bool GtkUiDelegateWayland::SetGtkWidgetTransientForImpl( + gfx::AcceleratedWidget parent, + base::OnceCallback callback) { auto* parent_window = connection_->wayland_window_manager()->GetWindow(parent); auto* foreign = connection_->xdg_foreign(); @@ -78,35 +35,13 @@ bool GtkUiDelegateWayland::SetGdkWindowTransientFor( DCHECK_EQ(parent_window->type(), PlatformWindowType::kWindow); - foreign->ExportSurfaceToForeign( - parent_window, base::BindOnce(&GtkUiDelegateWayland::OnHandle, - weak_factory_.GetWeakPtr(), window)); + foreign->ExportSurfaceToForeign(parent_window, std::move(callback)); return true; } -void GtkUiDelegateWayland::ClearTransientFor(gfx::AcceleratedWidget parent) { - // Nothing to do here. -} - -void GtkUiDelegateWayland::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); -} - int GtkUiDelegateWayland::GetGdkKeyState() { // TODO(crbug/1159460): Test fcitx unikey IME on ozone/wayland. return connection_->event_source()->keyboard_modifiers(); } -void GtkUiDelegateWayland::OnHandle(GdkWindow* window, - const std::string& handle) { - char* parent = const_cast(handle.c_str()); -#if GTK_CHECK_VERSION(3, 90, 0) - gdk_wayland_toplevel_set_transient_for_exported(GDK_TOPLEVEL(window), parent); -#else - gdk_wayland_window_set_transient_for_exported(window, parent); -#endif -} - } // namespace ui 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 index d198057b8ca..64daa368936 100644 --- a/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h +++ b/chromium/ui/ozone/platform/wayland/host/gtk_ui_delegate_wayland.h @@ -5,41 +5,27 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_UI_DELEGATE_WAYLAND_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_UI_DELEGATE_WAYLAND_H_ -#include - -#include "base/memory/weak_ptr.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gtk/gtk_ui_delegate.h" +#include "ui/gtk/wayland/gtk_ui_delegate_wayland_base.h" namespace ui { class WaylandConnection; -class GtkUiDelegateWayland : public GtkUiDelegate { +class GtkUiDelegateWayland : public GtkUiDelegateWaylandBase { public: explicit GtkUiDelegateWayland(WaylandConnection* connection); - GtkUiDelegateWayland(const GtkUiDelegateWayland&) = delete; - GtkUiDelegateWayland& operator=(const GtkUiDelegateWayland&) = delete; ~GtkUiDelegateWayland() override; + // GtkUiDelegateWaylandBase: + bool SetGtkWidgetTransientForImpl( + gfx::AcceleratedWidget parent, + base::OnceCallback callback) override; + // GtkUiDelegate: - void OnInitialized() override; - GdkKeymap* GetGdkKeymap() override; - GdkWindow* GetGdkWindow(gfx::AcceleratedWidget window_id) override; - bool SetGdkWindowTransientFor(GdkWindow* window, - gfx::AcceleratedWidget parent) override; - void ClearTransientFor(gfx::AcceleratedWidget parent) override; - void ShowGtkWindow(GtkWindow* window) override; int GetGdkKeyState() override; private: - // Called when xdg-foreign exports a parent window passed in - // SetGdkWindowTransientFor. - void OnHandle(GdkWindow* window, const std::string& handle); - WaylandConnection* const connection_; - - base::WeakPtrFactory weak_factory_{this}; }; } // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.cc b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.cc new file mode 100644 index 00000000000..e5eaeeb02e1 --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.cc @@ -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. + +#include "ui/ozone/platform/wayland/host/proxy/wayland_proxy.h" + +#include "base/check.h" +#include "ui/platform_window/common/platform_window_defaults.h" + +namespace wl { + +namespace { +static WaylandProxy* g_instance = nullptr; +} + +// static +WaylandProxy* WaylandProxy::GetInstance() { + CHECK(ui::UseTestConfigForPlatformWindows()); + return g_instance; +} + +// static +void WaylandProxy::SetInstance(WaylandProxy* instance) { + CHECK(ui::UseTestConfigForPlatformWindows()); + g_instance = instance; +} + +} // namespace wl diff --git a/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h new file mode 100644 index 00000000000..fae92085432 --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy.h @@ -0,0 +1,88 @@ +// 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_PROXY_WAYLAND_PROXY_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_PROXY_WAYLAND_PROXY_H_ + +#include "base/component_export.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/platform_window/platform_window_init_properties.h" + +struct wl_buffer; +struct wl_display; +struct wl_surface; + +namespace gfx { +class Rect; +class Size; +} // namespace gfx + +namespace wl { + +// A proxy interface to Ozone/Wayland that is used by input emulation. The +// reason why this is needed is that input emulation mustn't be part of +// Chromium and only be used and compiled when there is a need to run tests. +// This nicely separates Ozone/Wayland from input emulation and provides just +// core functionality that input emulation needs from Ozone/Wayland. +class COMPONENT_EXPORT(WAYLAND_PROXY) WaylandProxy { + public: + class Delegate { + public: + // Invoked when a new window is created aka WaylandWindow is added to the + // list of windows stored by WaylandWindowManager. + virtual void OnWindowAdded(gfx::AcceleratedWidget widget) = 0; + + // Invoked when an existing surface is removed aka WaylandWindow is removed + // from the list of windows stored by WaylandWindowManager. + virtual void OnWindowRemoved(gfx::AcceleratedWidget widget) = 0; + + // Invoked when an existing surface is configured. + virtual void OnWindowConfigured(gfx::AcceleratedWidget widget) = 0; + + protected: + virtual ~Delegate() = default; + }; + + virtual ~WaylandProxy() = default; + + static WaylandProxy* GetInstance(); + + // Sets the delegate that will be notified about the events described above + // for the Delegate class. + virtual void SetDelegate(Delegate* delegate) = 0; + + // Returns the wl_display the WaylandConnection has the connection with. + virtual wl_display* GetDisplay() = 0; + + // Returns wl_surface that backs the |widget|. + virtual wl_surface* GetWlSurfaceForAcceleratedWidget( + gfx::AcceleratedWidget widget) = 0; + + // Creates and returns a shm based wl_buffer with |buffer_size|. The shared + // memory is hold until DestroyShmForWlBuffer is called. + virtual wl_buffer* CreateShmBasedWlBuffer(const gfx::Size& buffer_size) = 0; + + // When this is called, |buffer| becomes invalid and mustn't be used any more. + virtual void DestroyShmForWlBuffer(wl_buffer* buffer) = 0; + + // Schedules display flush that dispatches pending events. + virtual void ScheduleDisplayFlush() = 0; + + // Returns platform window type of a window backed by the |widget|. + virtual ui::PlatformWindowType GetWindowType( + gfx::AcceleratedWidget widget) = 0; + + // Returns bounds in px of the window backed by |widget|. + virtual gfx::Rect GetWindowBounds(gfx::AcceleratedWidget widget) = 0; + + virtual bool WindowHasPointerFocus(gfx::AcceleratedWidget widget) = 0; + virtual bool WindowHasKeyboardFocus(gfx::AcceleratedWidget widget) = 0; + + protected: + static void SetInstance(WaylandProxy* instance); +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_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 new file mode 100644 index 00000000000..93aedb6ef8b --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc @@ -0,0 +1,105 @@ +// 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/proxy/wayland_proxy_impl.h" + +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_shm_buffer.h" +#include "ui/ozone/platform/wayland/host/wayland_window.h" + +namespace wl { + +WaylandProxyImpl::WaylandProxyImpl(ui::WaylandConnection* connection) + : connection_(connection) { + WaylandProxy::SetInstance(this); +} + +WaylandProxyImpl::~WaylandProxyImpl() { + WaylandProxy::SetInstance(nullptr); + if (delegate_) + connection_->wayland_window_manager()->RemoveObserver(this); +} + +void WaylandProxyImpl::SetDelegate(WaylandProxy::Delegate* delegate) { + DCHECK(!delegate_); + delegate_ = delegate; + if (delegate_) + connection_->wayland_window_manager()->AddObserver(this); + else if (!delegate_) + connection_->wayland_window_manager()->RemoveObserver(this); +} + +wl_display* WaylandProxyImpl::GetDisplay() { + return connection_->display(); +} + +wl_surface* WaylandProxyImpl::GetWlSurfaceForAcceleratedWidget( + gfx::AcceleratedWidget widget) { + auto* window = connection_->wayland_window_manager()->GetWindow(widget); + DCHECK(window); + return window->root_surface()->surface(); +} + +wl_buffer* WaylandProxyImpl::CreateShmBasedWlBuffer( + const gfx::Size& buffer_size) { + ui::WaylandShmBuffer shm_buffer(connection_->shm(), buffer_size); + auto* wlbuffer = shm_buffer.get(); + DCHECK(wlbuffer); + shm_buffers_.emplace_back(std::move(shm_buffer)); + return wlbuffer; +} + +void WaylandProxyImpl::DestroyShmForWlBuffer(wl_buffer* buffer) { + auto it = + std::find_if(shm_buffers_.begin(), shm_buffers_.end(), + [buffer](const auto& buf) { return buf.get() == buffer; }); + DCHECK(it != shm_buffers_.end()); + shm_buffers_.erase(it); +} + +void WaylandProxyImpl::ScheduleDisplayFlush() { + connection_->ScheduleFlush(); +} + +ui::PlatformWindowType WaylandProxyImpl::GetWindowType( + gfx::AcceleratedWidget widget) { + auto* window = connection_->wayland_window_manager()->GetWindow(widget); + DCHECK(window); + return window->type(); +} + +gfx::Rect WaylandProxyImpl::GetWindowBounds(gfx::AcceleratedWidget widget) { + auto* window = connection_->wayland_window_manager()->GetWindow(widget); + DCHECK(window); + return window->GetBounds(); +} + +bool WaylandProxyImpl::WindowHasPointerFocus(gfx::AcceleratedWidget widget) { + auto* window = connection_->wayland_window_manager()->GetWindow(widget); + DCHECK(window); + return window->has_pointer_focus(); +} + +bool WaylandProxyImpl::WindowHasKeyboardFocus(gfx::AcceleratedWidget widget) { + auto* window = connection_->wayland_window_manager()->GetWindow(widget); + DCHECK(window); + return window->has_keyboard_focus(); +} + +void WaylandProxyImpl::OnWindowAdded(ui::WaylandWindow* window) { + DCHECK(delegate_); + delegate_->OnWindowAdded(window->GetWidget()); +} + +void WaylandProxyImpl::OnWindowRemoved(ui::WaylandWindow* window) { + DCHECK(delegate_); + delegate_->OnWindowRemoved(window->GetWidget()); +} + +void WaylandProxyImpl::OnWindowConfigured(ui::WaylandWindow* window) { + DCHECK(delegate_); + delegate_->OnWindowConfigured(window->GetWidget()); +} + +} // namespace wl 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 new file mode 100644 index 00000000000..9805441d0b6 --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.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_OZONE_PLATFORM_WAYLAND_HOST_PROXY_WAYLAND_PROXY_IMPL_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_PROXY_WAYLAND_PROXY_IMPL_H_ + +#include + +#include "ui/ozone/platform/wayland/host/proxy/wayland_proxy.h" +#include "ui/ozone/platform/wayland/host/wayland_window_observer.h" + +namespace ui { +class WaylandConnection; +class WaylandShmBuffer; +} // namespace ui + +namespace wl { + +class WaylandProxyImpl : public WaylandProxy, public ui::WaylandWindowObserver { + public: + explicit WaylandProxyImpl(ui::WaylandConnection* connection); + ~WaylandProxyImpl() override; + + // WaylandProxy overrides: + void SetDelegate(WaylandProxy::Delegate* delegate) override; + wl_display* GetDisplay() override; + wl_surface* GetWlSurfaceForAcceleratedWidget( + gfx::AcceleratedWidget widget) override; + wl_buffer* CreateShmBasedWlBuffer(const gfx::Size& buffer_size) override; + void DestroyShmForWlBuffer(wl_buffer* buffer) override; + void ScheduleDisplayFlush() override; + ui::PlatformWindowType GetWindowType(gfx::AcceleratedWidget widget) override; + gfx::Rect GetWindowBounds(gfx::AcceleratedWidget widget) override; + bool WindowHasPointerFocus(gfx::AcceleratedWidget widget) override; + bool WindowHasKeyboardFocus(gfx::AcceleratedWidget widget) override; + + private: + // ui::WaylandWindowObserver overrides: + void OnWindowAdded(ui::WaylandWindow* window) override; + void OnWindowRemoved(ui::WaylandWindow* window) override; + void OnWindowConfigured(ui::WaylandWindow* window) override; + + ui::WaylandConnection* const connection_; + + WaylandProxy::Delegate* delegate_ = nullptr; + + std::vector shm_buffers_; +}; + +} // namespace wl + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_PROXY_WAYLAND_PROXY_IMPL_H_ diff --git a/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h b/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h index 8767166a13d..3ebab994100 100644 --- a/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h +++ b/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h @@ -5,7 +5,8 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_ -#include "base/strings/string16.h" +#include + #include "ui/ozone/platform/wayland/common/wayland_object.h" namespace gfx { @@ -64,7 +65,7 @@ class ShellToplevelWrapper { uint32_t hittest) = 0; // Sets a title of a native window. - virtual void SetTitle(const base::string16& title) = 0; + virtual void SetTitle(const std::u16string& title) = 0; // Sends acknowledge configure event back to wayland. virtual void AckConfigure(uint32_t serial) = 0; diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc b/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc index 7d8cb1086f5..3f253b2d491 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc @@ -13,8 +13,11 @@ namespace ui { WaylandAuxiliaryWindow::WaylandAuxiliaryWindow(PlatformWindowDelegate* delegate, - WaylandConnection* connection) - : WaylandWindow(delegate, connection) {} + WaylandConnection* connection, + WaylandWindow* parent) + : WaylandWindow(delegate, connection) { + set_parent_window(parent); +} WaylandAuxiliaryWindow::~WaylandAuxiliaryWindow() = default; @@ -30,6 +33,7 @@ void WaylandAuxiliaryWindow::Show(bool inactive) { void WaylandAuxiliaryWindow::Hide() { if (!subsurface_) return; + WaylandWindow::Hide(); subsurface_.reset(); @@ -58,30 +62,35 @@ void WaylandAuxiliaryWindow::SetBounds(const gfx::Rect& bounds) { } void WaylandAuxiliaryWindow::CreateSubsurface() { - auto* parent = FindParentWindow(); - set_parent_window(parent); + // wl_subsurface can be used for either tooltips or drag arrow windows. + // If we are in a drag process, the current parent is the entered window, so + // reparent the surface unconditionally. + if (connection()->IsDragInProgress()) + set_parent_window(connection()->data_drag_controller()->entered_window()); + + if (!parent_window()) { + LOG(WARNING) << "Parent was not set for the auxiliary window; guessing it!"; + set_parent_window( + connection()->wayland_window_manager()->GetCurrentFocusedWindow()); + } + + DCHECK(parent_window()); // We need to make sure that buffer scale matches the parent window. UpdateBufferScale(true); - // Tooltip and drag arrow creation is an async operation. By the time Aura - // actually creates them, it is possible that the user has already moved the - // mouse/pointer out of the window that triggered the tooltip, or user is no - // longer in a drag/drop process. In this case, parent is nullptr. - if (!parent) - return; - - subsurface_ = root_surface()->CreateSubsurface(parent->root_surface()); + subsurface_ = + root_surface()->CreateSubsurface(parent_window()->root_surface()); auto subsurface_bounds_dip = - wl::TranslateWindowBoundsToParentDIP(this, parent); + wl::TranslateWindowBoundsToParentDIP(this, parent_window()); DCHECK(subsurface_); // Convert position to DIP. wl_subsurface_set_position(subsurface_.get(), subsurface_bounds_dip.x(), subsurface_bounds_dip.y()); wl_subsurface_set_desync(subsurface_.get()); - parent->root_surface()->Commit(); + parent_window()->root_surface()->Commit(); connection()->ScheduleFlush(); // Notify the observers the window has been configured. Please note that @@ -90,34 +99,8 @@ void WaylandAuxiliaryWindow::CreateSubsurface() { connection()->wayland_window_manager()->NotifyWindowConfigured(this); } -WaylandWindow* WaylandAuxiliaryWindow::FindParentWindow() { - // wl_subsurface can be used for several purposes: tooltips and drag arrow - // windows. If we are in a drag process, use the entered window. Otherwise, - // it must be a tooltip. - if (connection()->IsDragInProgress()) - return connection()->data_drag_controller()->entered_window(); - - // We get the current focused window to place and show the - // tooltips. - return connection()->wayland_window_manager()->GetCurrentFocusedWindow(); -} - bool WaylandAuxiliaryWindow::OnInitialize( PlatformWindowInitProperties properties) { - DCHECK(!parent_window()); - - // If we do not have parent window provided, we must always use a focused - // window or a window that entered drag whenever the subsurface is created. - if (properties.parent_widget == gfx::kNullAcceleratedWidget) { - // Need to set the possible parent window here, so the initial scale will be - // calculated correctly. - set_parent_window(FindParentWindow()); - return true; - } - - set_parent_window( - connection()->wayland_window_manager()->FindParentForNewWindow( - properties.parent_widget)); return true; } diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.h b/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.h index 0fb87289e10..3035bd31613 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_auxiliary_window.h @@ -13,7 +13,8 @@ namespace ui { class WaylandAuxiliaryWindow : public WaylandWindow { public: WaylandAuxiliaryWindow(PlatformWindowDelegate* delegate, - WaylandConnection* connection); + WaylandConnection* connection, + WaylandWindow* parent); WaylandAuxiliaryWindow(const WaylandAuxiliaryWindow&) = delete; WaylandAuxiliaryWindow& operator=(const WaylandAuxiliaryWindow&) = delete; ~WaylandAuxiliaryWindow() override; @@ -31,9 +32,6 @@ class WaylandAuxiliaryWindow : public WaylandWindow { // Creates (if necessary) and shows a subsurface window. void CreateSubsurface(); - // Finds an appropriate parent window. - WaylandWindow* FindParentWindow(); - wl::Object subsurface_; }; 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 0a6e6d5b9d6..f7e0453ff7d 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 @@ -86,7 +86,8 @@ void WaylandBufferManagerConnector::OnBufferManagerHostPtrBinded( #endif buffer_manager_gpu_remote->Initialize( std::move(buffer_manager_host), buffer_formats_with_modifiers, - supports_dma_buf, buffer_manager_host_->SupportsAcquireFence()); + supports_dma_buf, buffer_manager_host_->SupportsViewporter(), + buffer_manager_host_->SupportsAcquireFence()); } void WaylandBufferManagerConnector::OnTerminateGpuProcess(std::string message) { 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 831babb51b4..bd1e5231354 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 @@ -8,6 +8,7 @@ #include #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/i18n/number_formatting.h" #include "base/stl_util.h" #include "base/strings/strcat.h" @@ -71,13 +72,13 @@ struct WaylandBufferManagerHost::Frame { void PendingActionComplete() { DCHECK(base::CurrentUIThread::IsSet()); CHECK_GT(pending_actions, 0u); - if (!--pending_actions) - if (!std::move(frame_commit_cb).Run()) { - buffer_manager_->error_message_ = - base::StrCat({"Buffer with ", NumberToString(buffer_id), - " id does not exist or failed to be created."}); - buffer_manager_->TerminateGpuProcess(); - } + if (!--pending_actions && !frame_commit_cb.is_null() && + !std::move(frame_commit_cb).Run()) { + buffer_manager_->error_message_ = + base::StrCat({"Buffer with ", NumberToString(buffer_id), + " id does not exist or failed to be created."}); + buffer_manager_->TerminateGpuProcess(); + } } // |root_surface| and |buffer_id| are saved so this Frame can be destroyed to @@ -97,7 +98,8 @@ struct WaylandBufferManagerHost::Frame { // This runs WaylandBufferManagerHost::Surface::CommitBuffer() of // |root_surface| with |buffer_id|. - base::OnceCallback frame_commit_cb; + base::OnceCallback frame_commit_cb = + base::BindOnce([] { return true; }); base::WeakPtrFactory weak_factory; }; @@ -203,15 +205,11 @@ class WaylandBufferManagerHost::Surface { void ClearState() { buffers_.clear(); - wl_frame_callback_.reset(); - feedback_queue_ = PresentationFeedbackQueue(); ResetSurfaceContents(); + feedback_queue_.clear(); submitted_buffers_.clear(); - for (auto& pending_commit : pending_commits_) - std::move(pending_commit.post_commit_cb).Run(); - pending_commits_.clear(); connection_->ScheduleFlush(); } @@ -222,6 +220,33 @@ class WaylandBufferManagerHost::Surface { wayland_surface_->AttachBuffer(nullptr); wayland_surface_->Commit(); + wl_frame_callback_.reset(); + + for (auto& pending_commit : pending_commits_) { + std::move(pending_commit.post_commit_cb).Run(); + if (!pending_commit.buffer) + continue; + + submitted_buffers_.push_back( + SubmissionInfo{pending_commit.buffer->buffer_id, /*acked=*/false}); + if (connection_->presentation()) { + feedback_queue_.push_back( + {wl::Object(), + pending_commit.buffer->buffer_id, + gfx::PresentationFeedback::Failure(), + /*submission_completed=*/false}); + } + } + pending_commits_.clear(); + // Mutter sometimes does not call buffer.release if wl_surface role is + // destroyed, causing graphics freeze. Manually release them and trigger + // OnSubmission callbacks. + for (auto& buffer : submitted_buffers_) { + auto* buff = GetBuffer(buffer.buffer_id); + if (buff) + buff->released = true; + } + MaybeProcessSubmittedBuffers(); // ResetSurfaceContents happens upon WaylandWindow::Hide call, which // destroys xdg_surface, xdg_popup, etc. They are going to be reinitialized @@ -299,9 +324,11 @@ class WaylandBufferManagerHost::Surface { // received OnSubmission for that buffer, just damage the buffer and // commit the surface again. However, if the buffer is released, it's safe // to reattach the buffer. - if (submitted_buffers_.empty() || + bool should_attach_buffer = + submitted_buffers_.empty() || submitted_buffers_.back().buffer_id != buffer->buffer_id || - buffer->released) { + buffer->released; + if (should_attach_buffer) { // Once the BufferRelease is called, the buffer will be released. DCHECK(buffer->released); buffer->released = false; @@ -315,8 +342,13 @@ class WaylandBufferManagerHost::Surface { DamageBuffer(buffer); - if (wait_for_callback) + // On Mutter, we don't receive frame.callback acks if we don't attach a new + // wl_buffer. This is more likely to happen with overlay single-on-top + // strategy, which leads to graphics freeze. So only setup frame_callback + // when we're attaching a different buffer. + if (should_attach_buffer && wait_for_callback) SetupFrameCallback(); + SetupPresentationFeedback(buffer->buffer_id); CommitSurface(); @@ -425,9 +457,11 @@ class WaylandBufferManagerHost::Surface { break; } } - DCHECK(buffer); - DCHECK(!buffer->released); - buffer->released = true; + // It's possible to be unable to find the released buffer in + // |submitted_buffers_| due to the manual releasing in + // ResetSurfaceContents(). + if (buffer) + buffer->released = true; // A release means we may be able to send OnSubmission for previously // submitted buffers. @@ -775,12 +809,12 @@ WaylandBufferManagerHost::BindInterface() { } void WaylandBufferManagerHost::OnChannelDestroyed() { - buffer_manager_gpu_associated_.reset(); - receiver_.reset(); - for (auto& surface_pair : surfaces_) surface_pair.second->ClearState(); + buffer_manager_gpu_associated_.reset(); + receiver_.reset(); + anonymous_buffers_.clear(); pending_frames_.clear(); } @@ -805,6 +839,10 @@ bool WaylandBufferManagerHost::SupportsAcquireFence() const { return !!connection_->linux_explicit_synchronization_v1(); } +bool WaylandBufferManagerHost::SupportsViewporter() const { + return !!connection_->viewporter(); +} + void WaylandBufferManagerHost::SetWaylandBufferManagerGpu( mojo::PendingAssociatedRemote buffer_manager_gpu_associated) { @@ -939,7 +977,6 @@ bool WaylandBufferManagerHost::CommitBufferInternal( base::OnceClosure subsurface_committed_cb = base::DoNothing(); if (!pending_frames_.empty() && commit_synced_subsurface) { pending_frames_.back()->IncrementPendingActions(); - subsurface_committed_cb.Reset(); subsurface_committed_cb = base::BindOnce(&WaylandBufferManagerHost::Frame::PendingActionComplete, pending_frames_.back()->weak_factory.GetWeakPtr()); @@ -1065,6 +1102,11 @@ void WaylandBufferManagerHost::ResetSurfaceContents( WaylandSurface* wayland_surface) { auto* surface = GetSurface(wayland_surface); DCHECK(surface); + for (auto& pending_frame : pending_frames_) { + if (pending_frame->root_surface == wayland_surface) { + pending_frame->frame_commit_cb = base::BindOnce([] { return true; }); + } + } surface->ResetSurfaceContents(); } 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 8137f562f07..fac32a14e72 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 @@ -110,6 +110,7 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost, bool SupportsDmabuf() const; bool SupportsAcquireFence() const; + bool SupportsViewporter() const; // ozone::mojom::WaylandBufferManagerHost overrides: // diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc index f6984d4ff54..aae5b5f2552 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc @@ -8,6 +8,7 @@ #include #include "base/check.h" +#include "base/containers/contains.h" #include "base/memory/scoped_refptr.h" #include "base/notreached.h" #include "base/optional.h" @@ -42,7 +43,6 @@ class Clipboard { // Asynchronously reads clipboard content with |mime_type| format. The result // data is expected to arrive through OnSelectionDataReceived() callback. virtual bool Read(const std::string& mime_type, - ui::PlatformClipboard::DataMap* data_map, ui::PlatformClipboard::RequestDataClosure callback) = 0; // Synchronously stores and announces |data| as available from this clipboard. @@ -79,14 +79,12 @@ class ClipboardImpl final : public Clipboard, // TODO(crbug.com/1165466): Support nested clipboard requests. bool Read(const std::string& mime_type, - ui::PlatformClipboard::DataMap* data_map, ui::PlatformClipboard::RequestDataClosure callback) final { - DCHECK(data_map); - received_data_ = data_map; - read_clipboard_closure_ = std::move(callback); - - if (GetDevice()->RequestSelectionData(mime_type)) + requested_mime_type_ = mime_type; + if (GetDevice()->RequestSelectionData(GetMimeTypeForRequest(mime_type))) { + read_clipboard_closure_ = std::move(callback); return true; + } SetData(base::MakeRefCounted(), mime_type); return false; } @@ -108,7 +106,7 @@ class ClipboardImpl final : public Clipboard, } else { offered_data_ = *data; source_ = manager_->CreateSource(this); - source_->Offer(GetMimeTypes()); + source_->Offer(GetOfferedMimeTypes()); GetDevice()->SetSelectionSource(source_.get()); } } @@ -125,7 +123,7 @@ class ClipboardImpl final : public Clipboard, private: DataDevice* GetDevice() { return manager_->GetDevice(); } - std::vector GetMimeTypes() { + std::vector GetOfferedMimeTypes() { std::vector mime_types; for (const auto& data : offered_data_) { mime_types.push_back(data.first); @@ -135,20 +133,25 @@ class ClipboardImpl final : public Clipboard, return mime_types; } + std::string GetMimeTypeForRequest(const std::string& mime_type) { + if (mime_type != ui::kMimeTypeText) + return mime_type; + // Prioritize unicode for text data. + for (const auto& t : GetDevice()->GetAvailableMimeTypes()) { + if (t == ui::kMimeTypeTextUtf8 || t == ui::kMimeTypeLinuxString || + t == ui::kMimeTypeLinuxUtf8String || t == ui::kMimeTypeLinuxText) { + return t; + } + } + return mime_type; + } + void SetData(ui::PlatformClipboard::Data contents, const std::string& mime_type) { - if (!received_data_) - return; - - DCHECK(contents); - (*received_data_)[mime_type] = contents; - - if (!read_clipboard_closure_.is_null()) { - auto it = received_data_->find(mime_type); - DCHECK(it != received_data_->end()); - std::move(read_clipboard_closure_).Run(it->second); - } - received_data_ = nullptr; + CHECK_EQ(GetMimeTypeForRequest(requested_mime_type_), mime_type); + if (!read_clipboard_closure_.is_null()) + std::move(read_clipboard_closure_).Run(contents); + requested_mime_type_.clear(); } // WaylandDataDeviceBase::SelectionDelegate: @@ -193,13 +196,12 @@ class ClipboardImpl final : public Clipboard, // The data currently stored in a given clipboard buffer. ui::PlatformClipboard::DataMap offered_data_; - // Holds a temporary instance of the client's clipboard content - // so that we can asynchronously write to it. - ui::PlatformClipboard::DataMap* received_data_ = nullptr; - // Stores the callback to be invoked upon data reading from clipboard. ui::PlatformClipboard::RequestDataClosure read_clipboard_closure_; + // 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_; }; @@ -207,7 +209,6 @@ class ClipboardImpl final : public Clipboard, } // namespace wl namespace ui { - WaylandClipboard::WaylandClipboard(WaylandConnection* connection, WaylandDataDeviceManager* manager) : connection_(connection), @@ -235,12 +236,11 @@ void WaylandClipboard::OfferClipboardData( void WaylandClipboard::RequestClipboardData( ClipboardBuffer buffer, const std::string& mime_type, - PlatformClipboard::DataMap* data_map, PlatformClipboard::RequestDataClosure callback) { if (auto* clipboard = GetClipboard(buffer)) - clipboard->Read(mime_type, data_map, std::move(callback)); + clipboard->Read(mime_type, std::move(callback)); else - std::move(callback).Run(base::nullopt); + std::move(callback).Run(nullptr); } bool WaylandClipboard::IsSelectionOwner(ClipboardBuffer buffer) { diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h index 1b15f4f488e..4f080096d1e 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.h @@ -47,7 +47,6 @@ class WaylandClipboard : public PlatformClipboard { void RequestClipboardData( ClipboardBuffer buffer, const std::string& mime_type, - PlatformClipboard::DataMap* data_map, PlatformClipboard::RequestDataClosure callback) override; void GetAvailableMimeTypes( ClipboardBuffer buffer, 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 9318149af79..33134a359a6 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc @@ -14,7 +14,6 @@ #include "base/containers/contains.h" #include "base/containers/flat_set.h" #include "base/location.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/test/mock_callback.h" #include "base/threading/thread_task_runner_handle.h" @@ -120,19 +119,42 @@ TEST_P(WaylandClipboardTest, ReadFromClipboard) { // writes in some sample data, and we check it matches expectation. base::RunLoop run_loop; auto callback = base::BindOnce( - [](base::OnceClosure quit_closure, - const base::Optional& data) { - auto& bytes = data->get()->data(); - std::string string_data = std::string(bytes.begin(), bytes.end()); + [](base::OnceClosure quit_closure, const PlatformClipboard::Data& data) { + ASSERT_TRUE(data.get()); + std::string string_data(data->front_as(), data->size()); EXPECT_EQ(kSampleClipboardText, string_data); std::move(quit_closure).Run(); }, run_loop.QuitClosure()); - PlatformClipboard::DataMap read_data_; clipboard_->RequestClipboardData(ClipboardBuffer::kCopyPaste, - kMimeTypeTextUtf8, &read_data_, - std::move(callback)); + kMimeTypeTextUtf8, std::move(callback)); + Sync(); + run_loop.Run(); +} + +// Regression test for crbug.com/1183939. Ensures unicode mime types take +// priority over text/plain when reading text. +TEST_P(WaylandClipboardTest, ReadFromClipboardPrioritizeUtf) { + auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); + data_offer->OnOffer(kMimeTypeText, + ToClipboardData(std::string("ascii_text"))); + data_offer->OnOffer(kMimeTypeTextUtf8, + ToClipboardData(std::string("utf8_text"))); + data_device_manager_->data_device()->OnSelection(data_offer); + Sync(); + + base::RunLoop run_loop; + auto callback = base::BindOnce( + [](base::OnceClosure quit_closure, const PlatformClipboard::Data& data) { + std::string str(data->front_as(), data->size()); + EXPECT_EQ("utf8_text", str); + std::move(quit_closure).Run(); + }, + run_loop.QuitClosure()); + + clipboard_->RequestClipboardData(ClipboardBuffer::kCopyPaste, + kMimeTypeTextUtf8, std::move(callback)); Sync(); run_loop.Run(); } @@ -141,16 +163,13 @@ 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 base::Optional& data) { - auto& bytes = data->get()->data(); - std::string string_data = std::string(bytes.begin(), bytes.end()); - EXPECT_EQ("", string_data); - }); - PlatformClipboard::DataMap read_data_; + auto callback = base::BindOnce([](const PlatformClipboard::Data& data) { + ASSERT_TRUE(data.get()); + std::string string_data(data->front_as(), data->size()); + EXPECT_EQ("", string_data); + }); clipboard_->RequestClipboardData(ClipboardBuffer::kCopyPaste, - kMimeTypeTextUtf8, &read_data_, - std::move(callback)); + kMimeTypeTextUtf8, std::move(callback)); } TEST_P(WaylandClipboardTest, IsSelectionOwner) { @@ -180,45 +199,34 @@ TEST_P(WaylandClipboardTest, OverlapReadingFromDifferentBuffers) { // Post a read request for kSelection buffer, which will start its execution // after kCopyPaste request (below) starts. - PlatformClipboard::DataMap selection_data_; base::MockCallback selection_callback; EXPECT_CALL(selection_callback, Run(_)).Times(1); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&PlatformClipboard::RequestClipboardData, base::Unretained(clipboard_), ClipboardBuffer::kSelection, - kMimeTypeTextUtf8, base::Unretained(&selection_data_), - selection_callback.Get())); + kMimeTypeTextUtf8, selection_callback.Get())); // Instantly start a clipboard read request for kCopyPaste buffer (the actual // data transfer will take place asynchronously. See WaylandDataDevice impl) - // and ensure read callback is called and |copy_paste_data_| is filled as - // expected, regardless any other request that may arrive in the meantime. - PlatformClipboard::DataMap copy_paste_data_; + // and ensure read callback is called with the expected resulting data, + // regardless any other request that may arrive in the meantime. base::RunLoop run_loop; clipboard_->RequestClipboardData( - ClipboardBuffer::kCopyPaste, kMimeTypeTextUtf8, ©_paste_data_, + ClipboardBuffer::kCopyPaste, kMimeTypeTextUtf8, base::BindOnce( [](base::OnceClosure quit_closure, - const base::Optional& data) { - ASSERT_TRUE(data.has_value()); + const PlatformClipboard::Data& data) { + ASSERT_TRUE(data.get()); EXPECT_EQ(kSampleClipboardText, - std::string(data->get()->front_as(), - data->get()->size())); + std::string(data->front_as(), data->size())); std::move(quit_closure).Run(); }, run_loop.QuitClosure())); Sync(); run_loop.Run(); - - EXPECT_TRUE(selection_data_.empty()); - - EXPECT_EQ(1u, copy_paste_data_.size()); - EXPECT_TRUE(base::Contains(copy_paste_data_, kMimeTypeTextUtf8)); - auto contents = copy_paste_data_[kMimeTypeTextUtf8]; - EXPECT_EQ(kSampleClipboardText, - std::string(contents->front_as(), contents->size())); + Sync(); } INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc b/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc index 702328d0e9f..6c0501b0f95 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_connection.cc @@ -18,10 +18,13 @@ #include "base/strings/string_util.h" #include "base/task/current_thread.h" #include "base/threading/thread_task_runner_handle.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/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" #include "ui/ozone/platform/wayland/host/wayland_cursor.h" @@ -43,6 +46,7 @@ #include "ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.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" #if defined(USE_LIBWAYLAND_STUBS) #include @@ -60,7 +64,7 @@ constexpr uint32_t kMaxAuraShellVersion = 16; constexpr uint32_t kMaxCompositorVersion = 4; constexpr uint32_t kMaxCursorShapesVersion = 1; constexpr uint32_t kMaxGtkPrimarySelectionDeviceManagerVersion = 1; -constexpr uint32_t kMaxKeyboardExtensionVersion = 1; +constexpr uint32_t kMaxKeyboardExtensionVersion = 2; constexpr uint32_t kMaxLinuxDmabufVersion = 3; constexpr uint32_t kMaxSeatVersion = 5; constexpr uint32_t kMaxShmVersion = 1; @@ -162,6 +166,9 @@ bool WaylandConnection::Initialize() { if (!seat_) LOG(WARNING) << "No wl_seat object. The functionality may suffer."; + if (UseTestConfigForPlatformWindows()) + wayland_proxy_ = std::make_unique(this); + return true; } @@ -187,7 +194,7 @@ void WaylandConnection::SetPlatformCursor(wl_cursor* cursor_data, int buffer_scale) { if (!cursor_) return; - cursor_->SetPlatformShape(cursor_data, serial(), buffer_scale); + cursor_->SetPlatformShape(cursor_data, buffer_scale); } void WaylandConnection::SetCursorBufferListener( @@ -203,7 +210,7 @@ void WaylandConnection::SetCursorBitmap(const std::vector& bitmaps, int buffer_scale) { if (!cursor_) return; - cursor_->UpdateBitmap(bitmaps, hotspot_in_dips, serial(), buffer_scale); + cursor_->UpdateBitmap(bitmaps, hotspot_in_dips, buffer_scale); } bool WaylandConnection::IsDragInProgress() const { @@ -231,6 +238,9 @@ void WaylandConnection::UpdateInputDevices(wl_seat* seat, auto has_keyboard = capabilities & WL_SEAT_CAPABILITY_KEYBOARD; auto has_touch = capabilities & WL_SEAT_CAPABILITY_TOUCH; + // Container for devices. Can be empty. + std::vector devices; + if (!has_pointer) { pointer_.reset(); cursor_.reset(); @@ -242,19 +252,38 @@ void WaylandConnection::UpdateInputDevices(wl_seat* seat, cursor_ = std::make_unique(pointer_.get(), this); cursor_->set_listener(listener_); wayland_cursor_position_ = std::make_unique(); + + // Wayland doesn't expose InputDeviceType. + devices.emplace_back(InputDevice( + pointer_->id(), InputDeviceType::INPUT_DEVICE_UNKNOWN, "pointer")); } else { LOG(ERROR) << "Failed to get wl_pointer from seat"; } } + // Notify about mouse changes. + GetHotplugEventObserver()->OnMouseDevicesUpdated(devices); + + // Clear the local container to store a keyboard device now. + devices.clear(); if (!has_keyboard) { keyboard_.reset(); } else if (!keyboard_) { if (!CreateKeyboard()) { LOG(ERROR) << "Failed to create WaylandKeyboard"; + } else { + // Wayland doesn't expose InputDeviceType. + devices.emplace_back(InputDevice( + keyboard_->id(), InputDeviceType::INPUT_DEVICE_UNKNOWN, "keyboard")); } } + // Notify about mouse changes. + GetHotplugEventObserver()->OnKeyboardDevicesUpdated(devices); + + // TODO(msisov): wl_touch doesn't expose the display it belongs to. Thus, it's + // impossible to figure out the size of the touchscreen for TouchscreenDevice + // struct that should be passed to a DeviceDataManager instance. if (!has_touch) { touch_.reset(); } else if (!touch_) { @@ -264,6 +293,9 @@ void WaylandConnection::UpdateInputDevices(wl_seat* seat, LOG(ERROR) << "Failed to get wl_touch from seat"; } } + + // Notify update completed. + GetHotplugEventObserver()->OnDeviceListsComplete(); } bool WaylandConnection::CreateKeyboard() { @@ -280,6 +312,10 @@ bool WaylandConnection::CreateKeyboard() { return true; } +DeviceHotplugEventObserver* WaylandConnection::GetHotplugEventObserver() { + return DeviceDataManager::GetInstance(); +} + void WaylandConnection::CreateDataObjectsIfReady() { if (data_device_manager_ && seat_) { DCHECK(!data_drag_controller_); @@ -377,7 +413,7 @@ void WaylandConnection::Global(void* data, if (!connection->wayland_output_manager_) { connection->wayland_output_manager_ = - std::make_unique(); + std::make_unique(connection); } connection->wayland_output_manager_->AddWaylandOutput(name, output.release()); @@ -412,7 +448,7 @@ void WaylandConnection::Global(void* data, std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion)); connection->zwp_primary_selection_device_manager_ = std::make_unique(manager.release(), - connection); + connection); } else if (!connection->linux_explicit_synchronization_ && (strcmp(interface, "zwp_linux_explicit_synchronization_v1") == 0)) { diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_connection.h b/chromium/ui/ozone/platform/wayland/host/wayland_connection.h index 7624abc23d6..104b33c3774 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_connection.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_connection.h @@ -22,8 +22,13 @@ namespace gfx { class Point; } +namespace wl { +class WaylandProxy; +} + namespace ui { +class DeviceHotplugEventObserver; class WaylandBufferManagerHost; class WaylandCursor; class WaylandCursorBufferListener; @@ -156,7 +161,8 @@ class WaylandConnection { return gtk_primary_selection_device_manager_.get(); } - ZwpPrimarySelectionDeviceManager* zwp_primary_selection_device_manager() const { + ZwpPrimarySelectionDeviceManager* zwp_primary_selection_device_manager() + const { return zwp_primary_selection_device_manager_.get(); } @@ -190,6 +196,8 @@ class WaylandConnection { // possible. Returns true iff WaylandKeyboard was created. bool CreateKeyboard(); + DeviceHotplugEventObserver* GetHotplugEventObserver(); + // wl_registry_listener static void Global(void* data, wl_registry* registry, @@ -256,6 +264,11 @@ class WaylandConnection { std::unique_ptr data_drag_controller_; std::unique_ptr window_drag_controller_; + // 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. + std::unique_ptr wayland_proxy_; + // Manages Wayland windows. WaylandWindowManager wayland_window_manager_; diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc b/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc index bd32821c243..981ade1b03e 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor.cc @@ -36,27 +36,29 @@ void WaylandCursor::OnBufferRelease(void* data, wl_buffer* buffer) { void WaylandCursor::UpdateBitmap(const std::vector& cursor_image, const gfx::Point& hotspot_in_dips, - uint32_t serial, int buffer_scale) { DCHECK(connection_->shm()); if (!pointer_) return; if (!cursor_image.size()) - return HideCursor(serial); + return HideCursor(); const SkBitmap& image = cursor_image[0]; if (image.dimensions().isEmpty()) - return HideCursor(serial); + return HideCursor(); gfx::Size image_size = gfx::SkISizeToSize(image.dimensions()); WaylandShmBuffer buffer(connection_->shm(), image_size); if (!buffer.IsValid()) { LOG(ERROR) << "Failed to create SHM buffer for Cursor Bitmap."; - return HideCursor(serial); + return HideCursor(); } + buffer_scale_ = buffer_scale; + wl_surface_set_buffer_scale(pointer_surface_.get(), buffer_scale_); + static const struct wl_buffer_listener wl_buffer_listener { &WaylandCursor::OnBufferRelease }; @@ -64,14 +66,8 @@ void WaylandCursor::UpdateBitmap(const std::vector& cursor_image, wl::DrawBitmap(image, &buffer); - wl_surface_set_buffer_scale(pointer_surface_.get(), buffer_scale); - - wl_pointer_set_cursor(pointer_->wl_object(), serial, pointer_surface_.get(), - hotspot_in_dips.x(), hotspot_in_dips.y()); - wl_surface_damage(pointer_surface_.get(), 0, 0, image_size.width(), - image_size.height()); - wl_surface_attach(pointer_surface_.get(), buffer.get(), 0, 0); - wl_surface_commit(pointer_surface_.get()); + AttachAndCommit(buffer.get(), image_size.width(), image_size.height(), + hotspot_in_dips.x(), hotspot_in_dips.y()); auto* address = buffer.get(); buffers_.emplace(address, std::move(buffer)); @@ -81,29 +77,28 @@ void WaylandCursor::UpdateBitmap(const std::vector& cursor_image, } void WaylandCursor::SetPlatformShape(wl_cursor* cursor_data, - uint32_t serial, int buffer_scale) { if (!pointer_) return; - wl_cursor_image* cursor_image = cursor_data->images[0]; - wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(cursor_image); + animation_timer_.Stop(); - wl_pointer_set_cursor(pointer_->wl_object(), serial, pointer_surface_.get(), - cursor_image->hotspot_x, cursor_image->hotspot_y); - wl_surface_set_buffer_scale(pointer_surface_.get(), buffer_scale); - wl_surface_damage(pointer_surface_.get(), 0, 0, cursor_image->width, - cursor_image->height); - wl_surface_attach(pointer_surface_.get(), cursor_buffer, 0, 0); - wl_surface_commit(pointer_surface_.get()); + cursor_data_ = cursor_data; + buffer_scale_ = buffer_scale; + current_image_index_ = 0; + + wl_surface_set_buffer_scale(pointer_surface_.get(), buffer_scale_); + + SetPlatformShapeInternal(); if (listener_) listener_->OnCursorBufferAttached(cursor_data); } -void WaylandCursor::HideCursor(uint32_t serial) { +void WaylandCursor::HideCursor() { DCHECK(pointer_); - wl_pointer_set_cursor(pointer_->wl_object(), serial, nullptr, 0, 0); + wl_pointer_set_cursor(pointer_->wl_object(), connection_->serial(), nullptr, + 0, 0); wl_surface_attach(pointer_surface_.get(), nullptr, 0, 0); wl_surface_commit(pointer_surface_.get()); @@ -114,4 +109,47 @@ void WaylandCursor::HideCursor(uint32_t serial) { listener_->OnCursorBufferAttached(nullptr); } +void WaylandCursor::SetPlatformShapeInternal() { + DCHECK_GT(cursor_data_->image_count, 0U); + + // The image index is incremented every time the animation frame is committed. + // Here we reset the counter if the final frame in the series has been sent, + // so the new cycle of the animation starts. + if (current_image_index_ >= cursor_data_->image_count) + current_image_index_ = 0; + + wl_cursor_image* const cursor_image = + cursor_data_->images[current_image_index_]; + + AttachAndCommit(wl_cursor_image_get_buffer(cursor_image), cursor_image->width, + cursor_image->height, cursor_image->hotspot_x / buffer_scale_, + cursor_image->hotspot_y / buffer_scale_); + + if (cursor_data_->image_count > 1 && cursor_image->delay > 0) { + // If we have multiple frames, then we have animated cursor. Schedule + // sending the next frame. See also the comment above. + animation_timer_.Start( + FROM_HERE, base::TimeDelta::FromMilliseconds(cursor_image->delay), this, + &WaylandCursor::SetPlatformShapeInternal); + ++current_image_index_; + } +} + +void WaylandCursor::AttachAndCommit(wl_buffer* buffer, + uint32_t buffer_width, + uint32_t buffer_height, + uint32_t hotspot_x_dip, + uint32_t hotspot_y_dip) { + DCHECK(pointer_); + + wl_pointer_set_cursor(pointer_->wl_object(), connection_->serial(), + pointer_surface_.get(), hotspot_x_dip, hotspot_y_dip); + + wl_surface_damage(pointer_surface_.get(), 0, 0, buffer_width, buffer_height); + wl_surface_attach(pointer_surface_.get(), buffer, 0, 0); + wl_surface_commit(pointer_surface_.get()); + + connection_->ScheduleFlush(); +} + } // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor.h b/chromium/ui/ozone/platform/wayland/host/wayland_cursor.h index 16af372b4c0..8ee5c96859e 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor.h @@ -9,6 +9,7 @@ #include "base/containers/flat_map.h" #include "base/macros.h" +#include "base/timer/timer.h" #include "third_party/skia/include/core/SkSurface.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" #include "ui/ozone/platform/wayland/host/wayland_shm_buffer.h" @@ -58,12 +59,10 @@ class WaylandCursor { // again. void UpdateBitmap(const std::vector& bitmaps, const gfx::Point& hotspot_in_dips, - uint32_t serial, int buffer_scale); // Takes data managed by the platform (without taking ownership). void SetPlatformShape(wl_cursor* cursor_data, - uint32_t serial, int buffer_scale); void set_listener(WaylandCursorBufferListener* listener) { @@ -74,16 +73,31 @@ class WaylandCursor { // wl_buffer_listener: static void OnBufferRelease(void* data, wl_buffer* wl_buffer); - void HideCursor(uint32_t serial); + void HideCursor(); + + // Prepares the platform cursor data for use. Starts animation if needed. + void SetPlatformShapeInternal(); + + // Does all Wayland-level calls necessary to update the cursor shape. + void AttachAndCommit(wl_buffer* buffer, + uint32_t buffer_width, + uint32_t buffer_height, + uint32_t hotspot_x_dip, + uint32_t hotspot_y_dip); WaylandPointer* const pointer_; WaylandConnection* const connection_; - - WaylandCursorBufferListener* listener_ = nullptr; + const wl::Object pointer_surface_; // Holds the buffers and their memory until the compositor releases them. base::flat_map buffers_; - const wl::Object pointer_surface_; + WaylandCursorBufferListener* listener_ = nullptr; + + // Current platform cursor. + wl_cursor* cursor_data_ = nullptr; + size_t current_image_index_ = 0; + int buffer_scale_ = 1; + base::RepeatingTimer animation_timer_; DISALLOW_COPY_AND_ASSIGN(WaylandCursor); }; 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 5c0a72ebe2a..32c7d6ffc42 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc @@ -20,11 +20,12 @@ namespace { wl_cursor_theme* LoadCursorTheme(const std::string& name, int size, + float scale, wl_shm* shm) { // wl_cursor_theme_load() can return nullptr. We don't check that here but // have to be cautious when we actually load the shape. - return wl_cursor_theme_load((name.empty() ? nullptr : name.c_str()), size, - shm); + return wl_cursor_theme_load((name.empty() ? nullptr : name.c_str()), + size * scale, shm); } } // namespace @@ -47,11 +48,7 @@ void WaylandCursorFactory::ObserveThemeChanges() { cursor_theme_observer_.Observe(cursor_theme_manager); } -base::Optional WaylandCursorFactory::GetDefaultCursor( - mojom::CursorType type) { - if (type == mojom::CursorType::kNone) - return nullptr; // nullptr is used for the hidden cursor. - +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); @@ -74,6 +71,14 @@ base::Optional WaylandCursorFactory::GetDefaultCursor( return static_cast(current_theme_->cache[type].get()); } +void WaylandCursorFactory::SetDeviceScaleFactor(float scale) { + if (scale_ == scale) + return; + + scale_ = scale; + ReloadThemeCursors(); +} + wl_cursor* WaylandCursorFactory::GetCursorFromTheme(const std::string& name) { // Possible if the theme could not be loaded. if (!current_theme_->theme) @@ -134,11 +139,11 @@ void WaylandCursorFactory::ReloadThemeCursors() { if (!base::ThreadPoolInstance::Get()) return; - base::PostTaskAndReplyWithResult( + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, - {base::ThreadPool(), base::MayBlock(), - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce(LoadCursorTheme, name_, size_, connection_->shm()->get()), + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + base::BindOnce(LoadCursorTheme, name_, size_, scale_, + connection_->shm()->get()), base::BindOnce(&WaylandCursorFactory::OnThemeLoaded, weak_factory_.GetWeakPtr(), name_, size_)); } 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 0be03bc1b43..d480fb20123 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.h @@ -9,7 +9,6 @@ #include "base/containers/flat_map.h" #include "base/memory/scoped_refptr.h" -#include "base/optional.h" #include "base/scoped_observation.h" #include "ui/base/cursor/cursor_theme_manager.h" #include "ui/base/cursor/cursor_theme_manager_observer.h" @@ -36,9 +35,9 @@ class WaylandCursorFactory : public BitmapCursorFactoryOzone, // CursorFactory: void ObserveThemeChanges() override; - // CursorFactoryOzone: - base::Optional GetDefaultCursor( - mojom::CursorType type) override; + // CursorFactory: + PlatformCursor GetDefaultCursor(mojom::CursorType type) override; + void SetDeviceScaleFactor(float scale) override; protected: // Returns the actual wl_cursor record from the currently loaded theme. @@ -78,6 +77,9 @@ class WaylandCursorFactory : public BitmapCursorFactoryOzone, // Current size of cursors int size_ = 24; + // The current scale of the mouse cursor icon. + float scale_ = 1.0f; + std::unique_ptr current_theme_; // Holds the reference on the unloaded theme until the cursor is released. std::unique_ptr unloaded_theme_; 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 1ea0e04b6cc..1d75ac374c4 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 @@ -85,7 +85,7 @@ TEST_P(WaylandCursorFactoryTest, RetainOldThemeUntilNewBufferIsAttached) { // that theme. { auto* const current_theme = cursor_factory_->current_theme_.get(); - auto const cursor = + auto* const cursor = cursor_factory_->GetDefaultCursor(mojom::CursorType::kPointer); EXPECT_NE(cursor, nullptr); EXPECT_GT(cursor_factory_->current_theme_->cache.size(), 0U); @@ -104,20 +104,20 @@ TEST_P(WaylandCursorFactoryTest, RetainOldThemeUntilNewBufferIsAttached) { EXPECT_NE(cursor_factory_->current_theme_.get(), current_theme); EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), current_theme); - cursor_factory_->OnCursorBufferAttached(reinterpret_cast( - reinterpret_cast(*cursor)->platform_data())); + cursor_factory_->OnCursorBufferAttached(static_cast( + static_cast(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 = + auto* const cursor = cursor_factory_->GetDefaultCursor(mojom::CursorType::kPointer); EXPECT_NE(cursor, nullptr); - cursor_factory_->OnCursorBufferAttached(reinterpret_cast( - reinterpret_cast(*cursor)->platform_data())); + cursor_factory_->OnCursorBufferAttached(static_cast( + static_cast(cursor)->platform_data())); EXPECT_EQ(cursor_factory_->unloaded_theme_.get(), nullptr); } 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 01f32113363..467944f1d96 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/files/scoped_file.h" +#include "base/logging.h" #include "ui/gfx/geometry/point_f.h" #include "ui/ozone/platform/wayland/common/data_util.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" 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 d81ce6155af..56400fa7070 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 @@ -7,6 +7,7 @@ #include #include "base/check.h" +#include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "third_party/skia/include/core/SkBitmap.h" 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 3e827a00928..cabd7bb976b 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 @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/containers/flat_set.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/clipboard/clipboard_constants.h" @@ -164,7 +163,7 @@ class WaylandDataDragControllerTest : public WaylandDragDropTest { WaylandWindow* window() { return window_.get(); } - base::string16 sample_text_for_dnd() const { + std::u16string sample_text_for_dnd() const { static auto text = base::ASCIIToUTF16(kSampleTextForDragAndDrop); return text; } @@ -204,7 +203,10 @@ class WaylandDataDragControllerTest : public WaylandDragDropTest { // drag sessions end up with no data transfer (cancelled). Otherwise, // it might lead to issues like https://crbug.com/1109324. EXPECT_CALL(*self->drop_handler(), OnDragLeave).Times(1); - EXPECT_CALL(*self->drag_handler(), OnDragFinished).Times(1); + // 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); self->Sync(); }, @@ -478,7 +480,7 @@ TEST_P(WaylandDataDragControllerTest, ValidateDroppedXMozUrl) { } else { EXPECT_TRUE(dropped_data->HasURL(kFilenameToURLPolicy)); GURL url; - base::string16 title; + std::u16string title; EXPECT_TRUE( dropped_data->GetURLAndTitle(kFilenameToURLPolicy, &url, &title)); EXPECT_EQ(url.spec(), kCase.expected_url); diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_source.h b/chromium/ui/ozone/platform/wayland/host/wayland_data_source.h index b78a7f1eaf0..d442fa48107 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_data_source.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_source.h @@ -95,7 +95,7 @@ class DataSource { Delegate* const delegate_; // Action selected by the compositor - uint32_t dnd_action_; + uint32_t dnd_action_ = 0; }; } // namespace wl 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 28f5892a0e9..46327d9631e 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc @@ -9,10 +9,12 @@ #include "base/bind.h" #include "base/check.h" +#include "base/logging.h" #include "base/optional.h" #include "base/time/time.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" +#include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/keyboard_code_conversion.h" @@ -97,11 +99,13 @@ void WaylandEventSource::OnKeyboardModifiersChanged(int modifiers) { keyboard_modifiers_ = modifiers; } -uint32_t WaylandEventSource::OnKeyboardKeyEvent(EventType type, - DomCode dom_code, - bool repeat, - base::TimeTicks timestamp, - int device_id) { +uint32_t WaylandEventSource::OnKeyboardKeyEvent( + EventType type, + DomCode dom_code, + bool repeat, + base::TimeTicks timestamp, + int device_id, + WaylandKeyboard::KeyEventKind kind) { DCHECK(type == ET_KEY_PRESSED || type == ET_KEY_RELEASED); DomKey dom_key; @@ -121,6 +125,13 @@ uint32_t WaylandEventSource::OnKeyboardKeyEvent(EventType type, KeyEvent event(type, key_code, dom_code, keyboard_modifiers_, dom_key, timestamp); event.set_source_device_id(device_id); + if (kind == WaylandKeyboard::KeyEventKind::kKey) { + // Mark that this is the key event which IME did not consume. + event.SetProperties({{ + kPropertyKeyboardImeFlag, + std::vector{kPropertyKeyboardImeIgnoredFlag}, + }}); + } return DispatchEvent(&event); } 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 ed0a6f85250..9617a85b41e 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.h @@ -87,7 +87,8 @@ class WaylandEventSource : public PlatformEventSource, DomCode dom_code, bool repeat, base::TimeTicks timestamp, - int device_id) override; + int device_id, + WaylandKeyboard::KeyEventKind kind) override; // WaylandPointer::Delegate void OnPointerFocusChanged(WaylandWindow* window, 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 b7e3c6b3238..c6b5dca39b9 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 @@ -17,6 +17,7 @@ #include "ui/base/ime/ime_text_span.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" +#include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/types/event_type.h" #include "ui/gfx/range/range.h" @@ -43,7 +44,7 @@ base::Optional OffsetFromUTF8Offset(const base::StringPiece& text, if (offset > text.length()) return base::nullopt; - base::string16 converted; + std::u16string converted; if (!base::UTF8ToUTF16(text.data(), offset, &converted)) return base::nullopt; @@ -85,6 +86,18 @@ bool IsImeEnabled() { return false; } +// Returns true if this event comes from extended_keyboard::peek_key. +// See also WaylandEventSource::OnKeyboardKeyEvent about how the flag is set. +bool IsPeekKeyEvent(const ui::KeyEvent& key_event) { + const auto* properties = key_event.properties(); + if (!properties) + return true; + auto it = properties->find(kPropertyKeyboardImeFlag); + if (it == properties->end()) + return true; + return !(it->second[0] & kPropertyKeyboardImeIgnoredFlag); +} + } // namespace WaylandInputMethodContext::WaylandInputMethodContext( @@ -123,8 +136,16 @@ void WaylandInputMethodContext::Init(bool initialize_for_testing) { bool WaylandInputMethodContext::DispatchKeyEvent( const ui::KeyEvent& key_event) { - if (key_event.type() != ET_KEY_PRESSED || - !character_composer_.FilterKeyPress(key_event)) + if (key_event.type() != ET_KEY_PRESSED) + return false; + + // Consume all peek key event. + if (IsPeekKeyEvent(key_event)) + return true; + + // This is the fallback key event which was not consumed by IME. + // So, process it inside Chrome. + if (!character_composer_.FilterKeyPress(key_event)) return false; // CharacterComposer consumed the key event. Update the composition text. @@ -136,7 +157,7 @@ bool WaylandInputMethodContext::DispatchKeyEvent( } void WaylandInputMethodContext::UpdatePreeditText( - const base::string16& preedit_text) { + const std::u16string& preedit_text) { CompositionText preedit; preedit.text = preedit_text; auto length = preedit.text.size(); @@ -177,7 +198,7 @@ void WaylandInputMethodContext::SetCursorLocation(const gfx::Rect& rect) { } void WaylandInputMethodContext::SetSurroundingText( - const base::string16& text, + const std::u16string& text, const gfx::Range& selection_range) { if (text_input_) text_input_->SetSurroundingText(text, selection_range); @@ -273,7 +294,8 @@ void WaylandInputMethodContext::OnKeysym(uint32_t keysym, EventType type = state == WL_KEYBOARD_KEY_STATE_PRESSED ? ET_KEY_PRESSED : ET_KEY_RELEASED; key_delegate_->OnKeyboardKeyEvent(type, dom_code, /*repeat=*/false, - EventTimeForNow(), device_id); + EventTimeForNow(), device_id, + WaylandKeyboard::KeyEventKind::kKey); #else NOTIMPLEMENTED(); #endif diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h index 19168e38390..912c3483043 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h @@ -36,7 +36,7 @@ class WaylandInputMethodContext : public LinuxInputMethodContext, // LinuxInputMethodContext overrides: bool DispatchKeyEvent(const ui::KeyEvent& key_event) override; void SetCursorLocation(const gfx::Rect& rect) override; - void SetSurroundingText(const base::string16& text, + void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; void Reset() override; void Focus() override; @@ -51,7 +51,7 @@ class WaylandInputMethodContext : public LinuxInputMethodContext, void OnKeysym(uint32_t keysym, uint32_t state, uint32_t modifiers) override; private: - void UpdatePreeditText(const base::string16& preedit_text); + void UpdatePreeditText(const std::u16string& preedit_text); WaylandConnection* const connection_; // TODO(jani) Handle this better 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 09936ef8d2f..ba1e5b0ef60 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 @@ -28,7 +28,7 @@ class TestInputMethodContextDelegate : public LinuxInputMethodContextDelegate { TestInputMethodContextDelegate() {} ~TestInputMethodContextDelegate() override {} - void OnCommit(const base::string16& text) override { + void OnCommit(const std::u16string& text) override { was_on_commit_called_ = true; } void OnPreeditChanged(const ui::CompositionText& composition_text) override { diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc index 812bdfcaf5a..85fcd6a423b 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.cc @@ -29,6 +29,48 @@ namespace ui { +class WaylandKeyboard::ZCRExtendedKeyboard { + public: + // Takes the ownership of |extended_keyboard|. + ZCRExtendedKeyboard(WaylandKeyboard* keyboard, + zcr_extended_keyboard_v1* extended_keyboard) + : keyboard_(keyboard), obj_(extended_keyboard) { + static constexpr zcr_extended_keyboard_v1_listener kListener = { + &ZCRExtendedKeyboard::PeekKey, + }; + zcr_extended_keyboard_v1_add_listener(obj_.get(), &kListener, this); + } + ZCRExtendedKeyboard(const ZCRExtendedKeyboard&) = delete; + ZCRExtendedKeyboard& operator=(const ZCRExtendedKeyboard&) = delete; + ~ZCRExtendedKeyboard() = default; + + void AckKey(uint32_t serial, bool handled) { + zcr_extended_keyboard_v1_ack_key(obj_.get(), serial, handled); + } + + // Returns true if connected object will send zcr_extended_keyboard::peek_key. + bool IsPeekKeySupported() { + return wl::get_version_of_object(obj_.get()) >= + ZCR_EXTENDED_KEYBOARD_V1_PEEK_KEY_SINCE_VERSION; + } + + private: + static void PeekKey(void* data, + zcr_extended_keyboard_v1* obj, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) { + auto* extended_keyboard = static_cast(data); + DCHECK(data); + extended_keyboard->keyboard_->OnKey( + serial, time, key, state, WaylandKeyboard::KeyEventKind::kPeekKey); + } + + WaylandKeyboard* const keyboard_; + wl::Object obj_; +}; + // static const wl_callback_listener WaylandKeyboard::callback_listener_ = { WaylandKeyboard::SyncCallback, @@ -54,9 +96,11 @@ WaylandKeyboard::WaylandKeyboard( wl_keyboard_add_listener(obj_.get(), &listener, this); // TODO(tonikitoo): Default auto-repeat to ON here? - if (keyboard_extension_v1) - extended_keyboard_v1_.reset(zcr_keyboard_extension_v1_get_extended_keyboard( - keyboard_extension_v1, obj_.get())); + if (keyboard_extension_v1) { + extended_keyboard_ = std::make_unique( + this, zcr_keyboard_extension_v1_get_extended_keyboard( + keyboard_extension_v1, obj_.get())); + } } WaylandKeyboard::~WaylandKeyboard() { @@ -122,18 +166,7 @@ void WaylandKeyboard::Key(void* data, uint32_t state) { WaylandKeyboard* keyboard = static_cast(data); DCHECK(keyboard); - - bool down = state == WL_KEYBOARD_KEY_STATE_PRESSED; - if (down) - keyboard->connection_->set_serial(serial, ET_KEY_PRESSED); - int device_id = keyboard->device_id(); - - keyboard->auto_repeat_handler_.UpdateKeyRepeat( - key, 0 /*scan_code*/, down, false /*suppress_auto_repeat*/, device_id); - - // TODO(tonikitoo,msisov): Handler 'repeat' parameter below. - keyboard->DispatchKey(key, 0 /*scan_code*/, down, false /*repeat*/, - EventTimeForNow(), device_id, EF_NONE); + keyboard->OnKey(serial, time, key, state, KeyEventKind::kKey); } void WaylandKeyboard::Modifiers(void* data, @@ -179,27 +212,69 @@ void WaylandKeyboard::FlushInput(base::OnceClosure closure) { connection_->ScheduleFlush(); } -void WaylandKeyboard::DispatchKey(uint32_t key, - uint32_t scan_code, +void WaylandKeyboard::DispatchKey(unsigned int key, + unsigned int scan_code, bool down, bool repeat, base::TimeTicks timestamp, int device_id, int flags) { + // Key repeat is only triggered by wl_keyboard::key event, + // but not by extended_keyboard::peek_key. + DispatchKey(key, scan_code, down, repeat, timestamp, device_id, flags, + KeyEventKind::kKey); +} + +void WaylandKeyboard::OnKey(uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state, + KeyEventKind kind) { + bool down = state == WL_KEYBOARD_KEY_STATE_PRESSED; + if (down) + connection_->set_serial(serial, ET_KEY_PRESSED); + + if (kind == KeyEventKind::kKey) { + auto_repeat_handler_.UpdateKeyRepeat(key, 0 /*scan_code*/, down, + false /*suppress_auto_repeat*/, + device_id()); + } + + // Block to dispatch RELEASE wl_keyboard::key event, if + // zcr_extended_keyboard::peek_key is supported, since the event is + // already dispatched. + // If not supported, dispatch it for compatibility. + if (kind == KeyEventKind::kKey && !down && extended_keyboard_ && + extended_keyboard_->IsPeekKeySupported()) { + return; + } + + // TODO(tonikitoo,msisov): Handler 'repeat' parameter below. + DispatchKey(key, 0 /*scan_code*/, down, false /*repeat*/, EventTimeForNow(), + device_id(), EF_NONE, kind); +} + +void WaylandKeyboard::DispatchKey(unsigned int key, + unsigned int scan_code, + bool down, + bool repeat, + base::TimeTicks timestamp, + int device_id, + int flags, + KeyEventKind kind) { DomCode dom_code = KeycodeConverter::EvdevCodeToDomCode(key); if (dom_code == ui::DomCode::NONE) return; // Pass empty DomKey and KeyboardCode here so the delegate can pre-process // and decode it when needed. - uint32_t result = - delegate_->OnKeyboardKeyEvent(down ? ET_KEY_PRESSED : ET_KEY_RELEASED, - dom_code, repeat, timestamp, device_id); + uint32_t result = delegate_->OnKeyboardKeyEvent( + down ? ET_KEY_PRESSED : ET_KEY_RELEASED, dom_code, repeat, timestamp, + device_id, kind); - if (extended_keyboard_v1_) { + if (extended_keyboard_) { bool handled = result & POST_DISPATCH_STOP_PROPAGATION; - zcr_extended_keyboard_v1_ack_key(extended_keyboard_v1_.get(), - connection_->serial(), handled); + extended_keyboard_->AckKey(connection_->serial(), handled); } } diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.h b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.h index d6f0b0bb025..cb882edc655 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard.h @@ -7,6 +7,8 @@ #include +#include + #include "base/time/time.h" #include "ui/base/buildflags.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -27,6 +29,12 @@ class XkbKeyboardLayoutEngine; class WaylandKeyboard : public EventAutoRepeatHandler::Delegate { public: class Delegate; + class ZCRExtendedKeyboard; + + enum class KeyEventKind { + kPeekKey, // Originated by extended_keyboard::peek_key. + kKey, // Originated by wl_keyboard::key. + }; WaylandKeyboard(wl_keyboard* keyboard, zcr_keyboard_extension_v1* keyboard_extension_v1, @@ -35,6 +43,7 @@ class WaylandKeyboard : public EventAutoRepeatHandler::Delegate { Delegate* delegate); virtual ~WaylandKeyboard(); + uint32_t id() const { return obj_.id(); } int device_id() const { return obj_.id(); } private: @@ -81,6 +90,23 @@ class WaylandKeyboard : public EventAutoRepeatHandler::Delegate { static void SyncCallback(void* data, struct wl_callback* cb, uint32_t time); + // Callback for wl_keyboard::key and extended_keyboard::peek_key. + void OnKey(uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state, + KeyEventKind kind); + + // Dispatches the key event. + void DispatchKey(unsigned int key, + unsigned int scan_code, + bool down, + bool repeat, + base::TimeTicks timestamp, + int device_id, + int flags, + KeyEventKind kind); + // EventAutoRepeatHandler::Delegate void FlushInput(base::OnceClosure closure) override; void DispatchKey(unsigned int key, @@ -92,7 +118,7 @@ class WaylandKeyboard : public EventAutoRepeatHandler::Delegate { int flags) override; wl::Object obj_; - wl::Object extended_keyboard_v1_; + std::unique_ptr extended_keyboard_; WaylandConnection* const connection_; Delegate* const delegate_; @@ -115,7 +141,8 @@ class WaylandKeyboard::Delegate { DomCode dom_code, bool repeat, base::TimeTicks timestamp, - int device_id) = 0; + int device_id, + WaylandKeyboard::KeyEventKind kind) = 0; protected: // Prevent deletion through a WaylandKeyboard::Delegate pointer. 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 927e5ad5893..91c1d3bec7a 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_keyboard_unittest.cc @@ -10,6 +10,7 @@ #include "base/timer/timer.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/devices/device_data_manager.h" #include "ui/events/event.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/test_keyboard.h" @@ -41,6 +42,9 @@ class WaylandKeyboardTest : public WaylandTest { Sync(); + EXPECT_EQ(1u, + DeviceDataManager::GetInstance()->GetKeyboardDevices().size()); + keyboard_ = server_.seat()->keyboard(); ASSERT_TRUE(keyboard_); diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_output.cc b/chromium/ui/ozone/platform/wayland/host/wayland_output.cc index 92d0f5be651..d0323e54797 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_output.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_output.cc @@ -4,6 +4,7 @@ #include "ui/ozone/platform/wayland/host/wayland_output.h" +#include "ui/display/display.h" #include "ui/gfx/color_space.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" @@ -13,9 +14,13 @@ WaylandOutput::WaylandOutput(uint32_t output_id, wl_output* output) : output_id_(output_id), output_(output), scale_factor_(kDefaultScaleFactor), - rect_in_physical_pixels_(gfx::Rect()) {} + rect_in_physical_pixels_(gfx::Rect()) { + wl_output_set_user_data(output_.get(), this); +} -WaylandOutput::~WaylandOutput() = default; +WaylandOutput::~WaylandOutput() { + wl_output_set_user_data(output_.get(), nullptr); +} void WaylandOutput::Initialize(Delegate* delegate) { DCHECK(!delegate_); @@ -29,6 +34,12 @@ void WaylandOutput::Initialize(Delegate* delegate) { wl_output_add_listener(output_.get(), &output_listener, this); } +float WaylandOutput::GetUIScaleFactor() const { + return display::Display::HasForceDeviceScaleFactor() + ? display::Display::GetForcedDeviceScaleFactor() + : scale_factor(); +} + void WaylandOutput::TriggerDelegateNotifications() const { DCHECK(!rect_in_physical_pixels_.IsEmpty()); delegate_->OnOutputHandleMetrics(output_id_, rect_in_physical_pixels_, diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_output.h b/chromium/ui/ozone/platform/wayland/host/wayland_output.h index 3bda676a179..0bf51f670aa 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_output.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_output.h @@ -33,6 +33,8 @@ class WaylandOutput { void Initialize(Delegate* delegate); + float GetUIScaleFactor() const; + uint32_t output_id() const { return output_id_; } bool has_output(wl_output* output) const { return output_.get() == output; } int32_t scale_factor() const { return scale_factor_; } diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.cc b/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.cc index 4d71d142fe7..731f5f1a11d 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.cc @@ -10,10 +10,12 @@ #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_window.h" namespace ui { -WaylandOutputManager::WaylandOutputManager() = default; +WaylandOutputManager::WaylandOutputManager(WaylandConnection* connection) + : connection_(connection) {} WaylandOutputManager::~WaylandOutputManager() = default; @@ -56,9 +58,8 @@ void WaylandOutputManager::RemoveWaylandOutput(uint32_t output_id) { output_list_.erase(output_it); } -std::unique_ptr WaylandOutputManager::CreateWaylandScreen( - WaylandConnection* connection) { - auto wayland_screen = std::make_unique(connection); +std::unique_ptr WaylandOutputManager::CreateWaylandScreen() { + auto wayland_screen = std::make_unique(connection_); wayland_screen_ = wayland_screen->GetWeakPtr(); // As long as |wl_output| sends geometry and other events asynchronously (that @@ -79,15 +80,6 @@ std::unique_ptr WaylandOutputManager::CreateWaylandScreen( return wayland_screen; } -uint32_t WaylandOutputManager::GetIdForOutput(wl_output* output) const { - auto output_it = std::find_if( - output_list_.begin(), output_list_.end(), - [output](const auto& item) { return item->has_output(output); }); - // This is unlikely to happen, but better to be explicit here. - DCHECK(output_it != output_list_.end()); - return output_it->get()->output_id(); -} - WaylandOutput* WaylandOutputManager::GetOutput(uint32_t id) const { auto output_it = GetOutputItById(id); // This is unlikely to happen, but better to be explicit here. @@ -95,6 +87,12 @@ WaylandOutput* WaylandOutputManager::GetOutput(uint32_t id) const { return output_it->get(); } +WaylandOutput* WaylandOutputManager::GetPrimaryOutput() const { + if (wayland_screen_) + return GetOutput(wayland_screen_->GetPrimaryDisplay().id()); + return nullptr; +} + void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id, const gfx::Rect& new_bounds, int32_t scale_factor) { @@ -102,6 +100,9 @@ void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id, wayland_screen_->OnOutputAddedOrUpdated(output_id, new_bounds, scale_factor); } + auto* wayland_window_manager = connection_->wayland_window_manager(); + for (auto* window : wayland_window_manager->GetWindowsOnOutput(output_id)) + window->UpdateBufferScale(true); } WaylandOutputManager::OutputList::const_iterator diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.h b/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.h index e02f10974c5..b9ec4ab5933 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_output_manager.h @@ -24,7 +24,7 @@ class WaylandOutput; class WaylandOutputManager : public WaylandOutput::Delegate { public: - WaylandOutputManager(); + explicit WaylandOutputManager(WaylandConnection* connection); ~WaylandOutputManager() override; // Says if at least one output has already been announced by a Wayland @@ -35,11 +35,10 @@ class WaylandOutputManager : public WaylandOutput::Delegate { void RemoveWaylandOutput(const uint32_t output_id); // Creates a platform screen and feeds it with existing outputs. - std::unique_ptr CreateWaylandScreen( - WaylandConnection* connection); + std::unique_ptr CreateWaylandScreen(); - uint32_t GetIdForOutput(wl_output* output) const; WaylandOutput* GetOutput(uint32_t id) const; + WaylandOutput* GetPrimaryOutput() const; WaylandScreen* wayland_screen() const { return wayland_screen_.get(); } @@ -55,6 +54,8 @@ class WaylandOutputManager : public WaylandOutput::Delegate { OutputList output_list_; + WaylandConnection* const connection_; + // Non-owned wayland screen instance. base::WeakPtr wayland_screen_; diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h b/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h index f9ad83b385a..70de3afd35a 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_pointer.h @@ -5,6 +5,8 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_POINTER_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_POINTER_H_ +#include + #include "base/macros.h" #include "ui/events/types/event_type.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" @@ -30,6 +32,7 @@ class WaylandPointer { Delegate* delegate); virtual ~WaylandPointer(); + uint32_t id() const { return obj_.id(); } wl_pointer* wl_object() const { return obj_.get(); } private: 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 94d56df903a..1334e8b8bae 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_pointer_unittest.cc @@ -12,6 +12,7 @@ #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/events/devices/device_data_manager.h" #include "ui/events/event.h" #include "ui/ozone/platform/wayland/host/wayland_cursor.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" @@ -41,6 +42,12 @@ class WaylandPointerTest : public WaylandTest { Sync(); + EXPECT_EQ(1u, DeviceDataManager::GetInstance()->GetMouseDevices().size()); + // Wayland doesn't expose touchpad devices separately. They are all + // WaylandPointers. + EXPECT_EQ(0u, + DeviceDataManager::GetInstance()->GetTouchpadDevices().size()); + pointer_ = server_.seat()->pointer(); ASSERT_TRUE(pointer_); } diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc b/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc index 736b2388374..22d8d81383c 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc @@ -16,8 +16,11 @@ namespace ui { WaylandPopup::WaylandPopup(PlatformWindowDelegate* delegate, - WaylandConnection* connection) - : WaylandWindow(delegate, connection) {} + WaylandConnection* connection, + WaylandWindow* parent) + : WaylandWindow(delegate, connection) { + set_parent_window(parent); +} WaylandPopup::~WaylandPopup() = default; @@ -56,6 +59,12 @@ void WaylandPopup::Show(bool inactive) { if (shell_popup_) return; + // Map parent window as WaylandPopup cannot become a visible child of a + // window that is not mapped. + DCHECK(parent_window()); + if (!parent_window()->IsVisible()) + parent_window()->Show(false); + if (!CreateShellPopup()) { Close(); return; @@ -72,6 +81,7 @@ void WaylandPopup::Hide() { if (child_window()) child_window()->Hide(); + WaylandWindow::Hide(); if (shell_popup_) { parent_window()->set_child_window(nullptr); diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_popup.h b/chromium/ui/ozone/platform/wayland/host/wayland_popup.h index 38af4fa80b4..efe07048d9b 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_popup.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_popup.h @@ -14,7 +14,9 @@ class ShellPopupWrapper; class WaylandPopup : public WaylandWindow { public: - WaylandPopup(PlatformWindowDelegate* delegate, WaylandConnection* connection); + WaylandPopup(PlatformWindowDelegate* delegate, + WaylandConnection* connection, + WaylandWindow* parent); ~WaylandPopup() override; ShellPopupWrapper* shell_popup() const { return shell_popup_.get(); } diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc b/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc index 42c13a25090..4adc30849ed 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc @@ -10,6 +10,7 @@ #include "base/containers/contains.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "ui/base/linux/linux_desktop.h" #include "ui/display/display.h" #include "ui/display/display_finder.h" #include "ui/display/display_list.h" @@ -128,10 +129,6 @@ void WaylandScreen::AddOrUpdateDisplay(uint32_t output_id, } display_list_.AddOrUpdateDisplay(changed_display, type); - - auto* wayland_window_manager = connection_->wayland_window_manager(); - for (auto* window : wayland_window_manager->GetWindowsOnOutput(output_id)) - window->UpdateBufferScale(true); } void WaylandScreen::OnTabletStateChanged(display::TabletState tablet_state) { @@ -162,8 +159,7 @@ display::Display WaylandScreen::GetDisplayForAcceleratedWidget( if (!window) return GetPrimaryDisplay(); - const auto* parent_window = window->parent_window(); - const auto entered_outputs_ids = window->entered_outputs_ids(); + const auto entered_output_id = window->GetPreferredEnteredOutputId(); // Although spec says a surface receives enter/leave surface events on // create/move/resize actions, this might be called right after a window is // created, but it has not been configured by a Wayland compositor and it @@ -171,22 +167,13 @@ display::Display WaylandScreen::GetDisplayForAcceleratedWidget( // switches between displays in a single output mode - Wayland may not send // enter events immediately, which can result in empty container of entered // ids (check comments in WaylandWindow::RemoveEnteredOutputId). In this - // case, it's also safe to return the primary display. A child window will - // most probably enter the same display than its parent so we return the - // parent's display if there is a parent. - if (entered_outputs_ids.empty()) { - if (parent_window) - return GetDisplayForAcceleratedWidget(parent_window->GetWidget()); + // case, it's also safe to return the primary display. + if (entered_output_id == 0) return GetPrimaryDisplay(); - } DCHECK(!display_list_.displays().empty()); - - // A widget can be located on two or more displays. It would be better if - // the most in DIP occupied display was returned, but it's impossible to do - // so in Wayland. Thus, return the one that was used the earliest. for (const auto& display : display_list_.displays()) { - if (display.id() == *entered_outputs_ids.begin()) + if (display.id() == entered_output_id) return display; } @@ -262,4 +249,13 @@ void WaylandScreen::RemoveObserver(display::DisplayObserver* observer) { display_list_.RemoveObserver(observer); } +base::Value WaylandScreen::GetGpuExtraInfoAsListValue( + const gfx::GpuExtraInfo& gpu_extra_info) { + // TODO(https://crbug.com/1138740): it'd be good to have the compositor name + // in the about://gpu as well. + auto list_value = GetDesktopEnvironmentInfoAsListValue(); + StorePlatformNameIntoListValue(list_value, "wayland"); + return list_value; +} + } // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_screen.h b/chromium/ui/ozone/platform/wayland/host/wayland_screen.h index 911892a51f1..3a9dfa7d132 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_screen.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen.h @@ -60,6 +60,8 @@ class WaylandScreen : public PlatformScreen { const gfx::Rect& match_rect) const override; void AddObserver(display::DisplayObserver* observer) override; void RemoveObserver(display::DisplayObserver* observer) override; + base::Value GetGpuExtraInfoAsListValue( + const gfx::GpuExtraInfo& gpu_extra_info) override; private: void AddOrUpdateDisplay(uint32_t output_id, 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 865ebbe730b..300b6a7985c 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc @@ -88,7 +88,7 @@ class WaylandScreenTest : public WaylandTest { ASSERT_TRUE(output_manager_); EXPECT_TRUE(output_manager_->IsOutputReady()); - platform_screen_ = output_manager_->CreateWaylandScreen(connection_.get()); + platform_screen_ = output_manager_->CreateWaylandScreen(); } protected: @@ -270,7 +270,7 @@ TEST_P(WaylandScreenTest, GetAcceleratedWidgetAtScreenPoint) { CreateWaylandWindowWithProperties( gfx::Rect(window_->GetBounds().width() - 10, window_->GetBounds().height() - 10, 100, 100), - PlatformWindowType::kPopup, window_->GetWidget(), &delegate); + PlatformWindowType::kMenu, window_->GetWidget(), &delegate); Sync(); @@ -538,7 +538,7 @@ TEST_P(WaylandScreenTest, GetCursorScreenPoint) { CreateWaylandWindowWithProperties( gfx::Rect(second_window_bounds.width() - 10, second_window_bounds.height() - 10, 10, 20), - PlatformWindowType::kPopup, second_window->GetWidget(), &delegate); + PlatformWindowType::kMenu, second_window->GetWidget(), &delegate); Sync(); @@ -585,7 +585,7 @@ TEST_P(WaylandScreenTest, GetCursorScreenPoint) { CreateWaylandWindowWithProperties( gfx::Rect(menu_window_bounds.x() + menu_window_bounds.width(), menu_window_bounds.y() + 2, 10, 20), - PlatformWindowType::kPopup, second_window->GetWidget(), &delegate); + PlatformWindowType::kMenu, second_window->GetWidget(), &delegate); Sync(); diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc b/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc index 99906d1c6dd..69c7ba3443c 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc @@ -7,12 +7,14 @@ #include #include +#include "base/logging.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.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_subsurface.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" namespace ui { @@ -226,7 +228,13 @@ wl::Object WaylandSurface::CreateAndAddRegion( wl_compositor_create_region(connection_->compositor())); auto window_shape_in_dips = root_window_->GetWindowShape(); - if (window_shape_in_dips.has_value()) { + + // 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. + if (window_shape_in_dips.has_value() && !region_px.IsEmpty() && + root_window_->root_surface() != this && + root_window()->primary_subsurface()->wayland_surface() != this) { 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 8290a7ea497..cd657d763df 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc @@ -67,13 +67,11 @@ bool WaylandToplevelWindow::CreateShellToplevel() { } void WaylandToplevelWindow::ApplyPendingBounds() { - if (pending_bounds_dip_.IsEmpty()) + if (pending_configures_.empty()) return; DCHECK(shell_toplevel_); - SetBoundsDip(pending_bounds_dip_); - pending_bounds_dip_ = gfx::Rect(); - connection()->ScheduleFlush(); + SetBoundsDip(pending_configures_.back().bounds_dip); } void WaylandToplevelWindow::DispatchHostWindowDragMovement( @@ -115,6 +113,7 @@ void WaylandToplevelWindow::Hide() { child_window()->Hide(); set_child_window(nullptr); } + WaylandWindow::Hide(); shell_toplevel_.reset(); connection()->ScheduleFlush(); @@ -130,7 +129,7 @@ bool WaylandToplevelWindow::IsVisible() const { return !!shell_toplevel_ || state_ == PlatformWindowState::kMinimized; } -void WaylandToplevelWindow::SetTitle(const base::string16& title) { +void WaylandToplevelWindow::SetTitle(const std::u16string& title) { if (window_title_ == title) return; @@ -307,26 +306,41 @@ void WaylandToplevelWindow::HandleToplevelConfigure(int32_t width, } void WaylandToplevelWindow::HandleSurfaceConfigure(uint32_t serial) { - if (pending_bounds_dip_.size() == - gfx::ScaleToRoundedSize(GetBounds().size(), 1.f / buffer_scale())) { - // If |pending_bounds_dip_| matches GetBounds(), then a frame matching - // |pending_bounds_dip_| may not arrive soon, despite the window delegate - // receives the updated bounds. Without a new frame, UpdateVisualSize() is - // not invoked, leaving this |configure| unacknowledged. + if (pending_bounds_dip_ == + gfx::ScaleToRoundedRect(GetBounds(), 1.f / buffer_scale()) && + pending_configures_.empty()) { + // If |pending_bounds_dip_| matches GetBounds(), and |pending_configures_| + // is empty, implying that the window is already rendering at + // |pending_bounds_dip_|, then a frame matching |pending_bounds_dip_| may + // not arrive soon, despite the window delegate receives the updated bounds. + // Without a new frame, UpdateVisualSize() is not invoked, leaving this + // |configure| unacknowledged. // E.g. With static window content, |configure| that does not // change window size will not cause the window to redraw. // Hence, acknowledge this |configure| now to tell the Wayland compositor // that this window has been configured. shell_toplevel()->SetWindowGeometry(pending_bounds_dip_); shell_toplevel()->AckConfigure(serial); + connection()->ScheduleFlush(); + } else if (!pending_configures_.empty() && + pending_bounds_dip_.size() == + pending_configures_.back().bounds_dip.size()) { + // There is an existing pending_configure with the same size, do not push a + // new one. Instead, update the serial of the pending_configure. + pending_configures_.back().serial = serial; } else { // Otherwise, push the pending |configure| to |pending_configures_|, wait // for a frame update, which will invoke UpdateVisualSize(). - DCHECK_LT(pending_configures_.size(), 25u); - pending_configures_.push_back({pending_bounds_dip_.size(), serial}); + DCHECK_LT(pending_configures_.size(), 100u); + pending_configures_.push_back({pending_bounds_dip_, serial}); + // The Wayland compositor can generate xdg-shell.configure events more + // frequently than frame updates from gpu process. Throttle + // ApplyPendingBounds() such that we forward new bounds to + // PlatformWindowDelegate at most once per frame. + if (pending_configures_.size() <= 1) + ApplyPendingBounds(); } - - ApplyPendingBounds(); + pending_bounds_dip_ = gfx::Rect(); } void WaylandToplevelWindow::UpdateVisualSize(const gfx::Size& size_px) { @@ -335,16 +349,22 @@ void WaylandToplevelWindow::UpdateVisualSize(const gfx::Size& size_px) { if (!shell_toplevel_) return; auto size_dip = gfx::ScaleToRoundedSize(size_px, 1.f / buffer_scale()); - auto result = std::find_if( - pending_configures_.begin(), pending_configures_.end(), - [&size_dip](auto& configure) { return size_dip == configure.size_dip; }); - - if (result == pending_configures_.end()) - return; + auto result = + std::find_if(pending_configures_.begin(), pending_configures_.end(), + [&size_dip](auto& configure) { + return size_dip == configure.bounds_dip.size(); + }); + + if (result != pending_configures_.end()) { + shell_toplevel()->SetWindowGeometry(gfx::Rect(size_dip)); + shell_toplevel()->AckConfigure(result->serial); + connection()->ScheduleFlush(); + pending_configures_.erase(pending_configures_.begin(), ++result); + } - shell_toplevel()->SetWindowGeometry(gfx::Rect(size_dip)); - shell_toplevel()->AckConfigure(result->serial); - pending_configures_.erase(pending_configures_.begin(), ++result); + // UpdateVisualSize() indicates a frame update, which means we can forward new + // bounds now. Apply the latest pending_configure. + ApplyPendingBounds(); } bool WaylandToplevelWindow::OnInitialize( @@ -365,6 +385,18 @@ bool WaylandToplevelWindow::IsActive() const { return is_active_; } +void WaylandToplevelWindow::LockFrame(void* data, zaura_surface* surface) { + WaylandToplevelWindow* self = static_cast(data); + DCHECK(self); + self->OnFrameLockingChanged(true); +} + +void WaylandToplevelWindow::UnlockFrame(void* data, zaura_surface* surface) { + WaylandToplevelWindow* self = static_cast(data); + DCHECK(self); + self->OnFrameLockingChanged(false); +} + bool WaylandToplevelWindow::RunMoveLoop(const gfx::Vector2d& drag_offset) { DCHECK(connection()->window_drag_controller()); return connection()->window_drag_controller()->Drag(this, drag_offset); @@ -519,8 +551,17 @@ void WaylandToplevelWindow::InitializeAuraShellSurface() { DCHECK(shell_toplevel_); if (connection()->zaura_shell() && !aura_surface_) { + static const zaura_surface_listener zaura_surface_listener = { + nullptr, + &WaylandToplevelWindow::LockFrame, + &WaylandToplevelWindow::UnlockFrame, + }; + aura_surface_.reset(zaura_shell_get_aura_surface( connection()->zaura_shell()->wl_object(), root_surface()->surface())); + + zaura_surface_add_listener(aura_surface_.get(), &zaura_surface_listener, + this); SetImmersiveFullscreenStatus(false); } } @@ -544,6 +585,11 @@ void WaylandToplevelWindow::OnDecorationModeChanged() { } } +void WaylandToplevelWindow::OnFrameLockingChanged(bool lock) { + DCHECK(delegate()); + delegate()->OnSurfaceFrameLockingChanged(lock); +} + void WaylandToplevelWindow::UpdateWindowMask() { // TODO(http://crbug.com/1158733): When supporting PlatformWindow::SetShape, // update window region with the given |shape|. 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 849ee9ae60d..1c47f1c501e 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h @@ -43,7 +43,7 @@ class WaylandToplevelWindow : public WaylandWindow, void Show(bool inactive) override; void Hide() override; bool IsVisible() const override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void ToggleFullscreen() override; void Maximize() override; void Minimize() override; @@ -71,6 +71,11 @@ class WaylandToplevelWindow : public WaylandWindow, void UpdateVisualSize(const gfx::Size& size_px) override; bool OnInitialize(PlatformWindowInitProperties properties) override; bool IsActive() const override; + + // zaura_surface listeners + static void LockFrame(void* data, zaura_surface* surface); + static void UnlockFrame(void* data, zaura_surface* surface); + // Calls UpdateWindowShape, set_input_region and set_opaque_region // for this toplevel window. void UpdateWindowMask() override; @@ -107,6 +112,10 @@ class WaylandToplevelWindow : public WaylandWindow, // Sets decoration mode for a window. void OnDecorationModeChanged(); + // Called when frame is locked to normal state or unlocked from + // previously locked state. + void OnFrameLockingChanged(bool lock); + // Wrappers around shell surface. std::unique_ptr shell_toplevel_; @@ -142,7 +151,7 @@ class WaylandToplevelWindow : public WaylandWindow, #endif // Title of the ShellToplevel. - base::string16 window_title_; + std::u16string window_title_; // Max and min sizes of the WaylandToplevelWindow window. base::Optional min_size_; @@ -158,10 +167,10 @@ class WaylandToplevelWindow : public WaylandWindow, base::Optional> window_shape_in_dips_; - // Pending xdg-shell configures, once this window is drawn to |size_dip|, + // Pending xdg-shell configures, once this window is drawn to |bounds_dip|, // ack_configure with |serial| will be sent to the Wayland compositor. struct PendingConfigure { - gfx::Size size_dip; + gfx::Rect bounds_dip; uint32_t serial; }; base::circular_deque pending_configures_; diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window.cc index edc21c70b89..20a90ca60ba 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_window.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_window.cc @@ -9,8 +9,10 @@ #include #include "base/bind.h" +#include "base/memory/scoped_refptr.h" #include "base/run_loop.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/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data.h" @@ -33,11 +35,15 @@ #include "ui/ozone/platform/wayland/host/wayland_subsurface.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" #include "ui/platform_window/wm/wm_drag_handler.h" #include "ui/platform_window/wm/wm_drop_handler.h" +namespace ui { namespace { +using mojom::CursorType; + bool OverlayStackOrderCompare( const ui::ozone::mojom::WaylandOverlayConfigPtr& i, const ui::ozone::mojom::WaylandOverlayConfigPtr& j) { @@ -46,8 +52,6 @@ bool OverlayStackOrderCompare( } // namespace -namespace ui { - WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate, WaylandConnection* connection) : delegate_(delegate), @@ -55,7 +59,8 @@ WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate, wayland_overlay_delegation_enabled_(connection->viewporter() && IsWaylandOverlayDelegationEnabled()), accelerated_widget_( - connection->wayland_window_manager()->AllocateAcceleratedWidget()) { + connection->wayland_window_manager()->AllocateAcceleratedWidget()), + ui_task_runner_(base::ThreadTaskRunnerHandle::Get()) { // Set a class property key, which allows |this| to be used for drag action. SetWmDragHandler(this, this); } @@ -86,49 +91,79 @@ void WaylandWindow::OnWindowLostCapture() { void WaylandWindow::UpdateBufferScale(bool update_bounds) { DCHECK(connection_->wayland_output_manager()); - const auto* screen = connection_->wayland_output_manager()->wayland_screen(); - // The client might not create screen at all. - if (!screen) + auto preferred_outputs_id = GetPreferredEnteredOutputId(); + if (preferred_outputs_id == 0) { + // If non of the output are entered, use primary output. This is what + // WaylandScreen returns back to ScreenOzone. + auto* primary_output = + connection_->wayland_output_manager()->GetPrimaryOutput(); + // We don't know our primary output - WaylandScreen hasn't been created + // yet. + if (!primary_output) + return; + preferred_outputs_id = primary_output->output_id(); + } + + auto* output = + connection_->wayland_output_manager()->GetOutput(preferred_outputs_id); + // There can be a race between sending leave output event and destroying + // wl_outputs. Thus, explicitly check if the output exist. + if (!output) return; - const auto widget = GetWidget(); + int32_t new_scale = output->scale_factor(); + ui_scale_ = output->GetUIScaleFactor(); - int32_t new_scale = 0; - if (parent_window_) { - new_scale = parent_window_->buffer_scale(); - ui_scale_ = parent_window_->ui_scale_; - } else { - const auto display = (widget == gfx::kNullAcceleratedWidget) - ? screen->GetPrimaryDisplay() - : screen->GetDisplayForAcceleratedWidget(widget); - new_scale = connection_->wayland_output_manager() - ->GetOutput(display.id()) - ->scale_factor(); - - if (display::Display::HasForceDeviceScaleFactor()) - ui_scale_ = display::Display::GetForcedDeviceScaleFactor(); - else - ui_scale_ = display.device_scale_factor(); - } int32_t old_scale = buffer_scale(); root_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)); + + // Propagate update to the child windows + if (child_window_) + child_window_->UpdateBufferScale(update_bounds); } gfx::AcceleratedWidget WaylandWindow::GetWidget() const { return accelerated_widget_; } +uint32_t WaylandWindow::GetPreferredEnteredOutputId() { + // Child windows don't store entered outputs. Instead, take the window's + // root parent window and use its preferred output. + if (parent_window_) + return GetRootParentWindow()->GetPreferredEnteredOutputId(); + + // It can be either a toplevel window that hasn't entered any outputs yet, or + // still a non toplevel window that doesn't have a parent (for example, a + // wl_surface that is being dragged). + if (entered_outputs_.empty()) + return 0; + + DCHECK_EQ(PlatformWindowType::kWindow, type()); + + // 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 + // that was entered. This way, we can be sure that the contents of the Window + // are rendered at correct dpi when a user moves the window between displays. + auto* preferred_output = *entered_outputs_.begin(); + for (WaylandOutput* output : entered_outputs_) { + if (output->scale_factor() > preferred_output->scale_factor()) + preferred_output = output; + } + + return preferred_output->output_id(); +} + 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_) { + if (has_pointer_focus_ && bitmap_ && bitmap_->type() != CursorType::kNone) { // Check for theme-provided cursor. if (bitmap_->platform_data()) { connection_->SetPlatformCursor( @@ -175,7 +210,11 @@ void WaylandWindow::Show(bool inactive) { } void WaylandWindow::Hide() { - NOTREACHED(); + // Mutter compositor crashes if we don't remove subsurface roles when hiding. + if (primary_subsurface_) + primary_subsurface()->Hide(); + for (auto& subsurface : wayland_subsurfaces_) + subsurface->Hide(); } void WaylandWindow::Close() { @@ -193,9 +232,26 @@ void WaylandWindow::PrepareForShutdown() { } void WaylandWindow::SetBounds(const gfx::Rect& bounds_px) { - if (bounds_px_ == bounds_px) + gfx::Rect adjusted_bounds_px = bounds_px; + + if (const auto min_size = delegate_->GetMinimumSizeForWindow()) { + if (min_size->width() > 0 && adjusted_bounds_px.width() < min_size->width()) + adjusted_bounds_px.set_width(min_size->width()); + if (min_size->height() > 0 && + adjusted_bounds_px.height() < min_size->height()) + adjusted_bounds_px.set_height(min_size->height()); + } + if (const auto max_size = delegate_->GetMaximumSizeForWindow()) { + if (max_size->width() > 0 && adjusted_bounds_px.width() > max_size->width()) + adjusted_bounds_px.set_width(max_size->width()); + if (max_size->height() > 0 && + adjusted_bounds_px.height() > max_size->height()) + adjusted_bounds_px.set_height(max_size->height()); + } + + if (bounds_px_ == adjusted_bounds_px) return; - bounds_px_ = bounds_px; + bounds_px_ = adjusted_bounds_px; if (update_visual_size_immediately_) UpdateVisualSize(bounds_px.size()); @@ -206,7 +262,7 @@ gfx::Rect WaylandWindow::GetBounds() const { return bounds_px_; } -void WaylandWindow::SetTitle(const base::string16& title) {} +void WaylandWindow::SetTitle(const std::u16string& title) {} void WaylandWindow::SetCapture() { // Wayland doesn't allow explicit grabs. Instead, it sends events to "entered" @@ -262,6 +318,8 @@ bool WaylandWindow::ShouldUseNativeFrame() const { } void WaylandWindow::SetCursor(PlatformCursor cursor) { + DCHECK(cursor); + scoped_refptr bitmap = BitmapCursorFactoryOzone::GetBitmapCursor(cursor); if (bitmap_ == bitmap) @@ -269,7 +327,7 @@ void WaylandWindow::SetCursor(PlatformCursor cursor) { bitmap_ = bitmap; - if (!bitmap_) { + if (bitmap_->type() == CursorType::kNone) { // Hide the cursor. connection_->SetCursorBitmap(std::vector(), gfx::Point(), buffer_scale()); @@ -411,6 +469,8 @@ void WaylandWindow::HandlePopupConfigure(const gfx::Rect& bounds_dip) { } void WaylandWindow::UpdateVisualSize(const gfx::Size& size_px) { + if (visual_size_px_ == size_px) + return; visual_size_px_ = size_px; UpdateWindowMask(); } @@ -496,6 +556,10 @@ bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) { return false; } + // Update visual size in tests immediately if the test config is set. + // Otherwise, such tests as interactive_ui_tests fail. + set_update_visual_size_immediately(UseTestConfigForPlatformWindows()); + // Properties contain DIP bounds but the buffer scale is initially 1 so it's // OK to assign. The bounds will be recalculated when the buffer scale // changes. @@ -540,11 +604,8 @@ void WaylandWindow::AddEnteredOutputId(struct wl_output* output) { if (wl::IsMenuType(type()) || type() == ui::PlatformWindowType::kTooltip) return; - const uint32_t entered_output_id = - connection_->wayland_output_manager()->GetIdForOutput(output); - DCHECK_NE(entered_output_id, 0u); - auto result = entered_outputs_ids_.insert(entered_output_id); - DCHECK(result.first != entered_outputs_ids_.end()); + entered_outputs_.emplace_back( + static_cast(wl_output_get_user_data(output))); UpdateBufferScale(true); } @@ -556,17 +617,17 @@ void WaylandWindow::RemoveEnteredOutputId(struct wl_output* output) { if (wl::IsMenuType(type())) return; - const uint32_t left_output_id = - connection_->wayland_output_manager()->GetIdForOutput(output); - auto entered_output_id_it = entered_outputs_ids_.find(left_output_id); + auto entered_outputs_it_ = + std::find(entered_outputs_.begin(), entered_outputs_.end(), + static_cast(wl_output_get_user_data(output))); // Workaround: when a user switches physical output between two displays, // a window does not necessarily receive enter events immediately or until // a user resizes/moves the window. It means that switching output between // displays in a single output mode results in leave events, but the surface // might not have received enter event before. Thus, remove the id of left // output only if it was stored before. - if (entered_output_id_it != entered_outputs_ids_.end()) - entered_outputs_ids_.erase(entered_output_id_it); + if (entered_outputs_it_ != entered_outputs_.end()) + entered_outputs_.erase(entered_outputs_it_); UpdateBufferScale(true); } @@ -781,10 +842,15 @@ bool WaylandWindow::CommitOverlays( if (!num_primary_planes && overlays.front()->z_order == INT32_MIN) split = overlays.begin(); UpdateVisualSize((*split)->bounds_rect.size()); - root_surface_->SetViewportDestination(visual_size_px_); if (!wayland_overlay_delegation_enabled_) { root_surface_->SetViewportSource((*split)->crop_rect); + // TODO(fangzhoug): Refactor some of this logic s.t. the decision of whether + // to apply viewport.destination is made at commit time. + root_surface_->SetViewportDestination((*split)->crop_rect == + gfx::RectF(1.f, 1.f) + ? gfx::Size() + : (*split)->bounds_rect.size()); connection_->buffer_manager_host()->CommitBufferInternal( root_surface(), (*split)->buffer_id, (*split)->damage_region, /*wait_for_frame_callback=*/true); @@ -792,8 +858,15 @@ bool WaylandWindow::CommitOverlays( } if (num_primary_planes) { + // Mutter has incorrect damage when processing un-cropped buffer commits + // 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. primary_subsurface_->ConfigureAndShowSurface( - (*split)->transform, (*split)->crop_rect, (*split)->bounds_rect, + (*split)->transform, (*split)->crop_rect, + (*split)->crop_rect == gfx::RectF(1.f, 1.f) ? gfx::Rect() + : (*split)->bounds_rect, (*split)->enable_blend, nullptr, nullptr); connection_->buffer_manager_host()->CommitBufferInternal( primary_subsurface_->wayland_surface(), (*split)->buffer_id, @@ -810,6 +883,7 @@ bool WaylandWindow::CommitOverlays( should_attach_background_buffer_ = true; } + root_surface_->SetViewportDestination(visual_size_px_); if (should_attach_background_buffer_) { connection_->buffer_manager_host()->EndFrame(background_buffer_id_, background_damage); diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window.h b/chromium/ui/ozone/platform/wayland/host/wayland_window.h index 8bcc007f766..3c810edca97 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_window.h +++ b/chromium/ui/ozone/platform/wayland/host/wayland_window.h @@ -13,7 +13,8 @@ #include "base/callback.h" #include "base/containers/flat_set.h" #include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/single_thread_task_runner.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" @@ -33,6 +34,7 @@ class OSExchangeData; class WaylandConnection; class WaylandSubsurface; class WaylandWindowDragController; +class WaylandOutput; using WidgetSubsurfaceSet = base::flat_set>; @@ -104,8 +106,14 @@ class WaylandWindow : public PlatformWindow, int32_t buffer_scale() const { return root_surface_->buffer_scale(); } int32_t ui_scale() const { return ui_scale_; } - const base::flat_set& entered_outputs_ids() const { - return entered_outputs_ids_; + // 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. + // However, if all the outputs the window is located at have the same scale + // factor, the very first entered output is chosen as there is no way to + // figure out what output the window occupies the most. + uint32_t GetPreferredEnteredOutputId(); + const std::vector& entered_outputs() const { + return entered_outputs_; } // Returns current type of the window. @@ -134,7 +142,7 @@ class WaylandWindow : public PlatformWindow, void PrepareForShutdown() override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() const override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void SetCapture() override; void ReleaseCapture() override; bool HasCapture() const override; @@ -211,6 +219,10 @@ class WaylandWindow : public PlatformWindow, // not support that). virtual bool IsActive() const; + scoped_refptr ui_task_runner() { + return ui_task_runner_; + } + protected: WaylandWindow(PlatformWindowDelegate* delegate, WaylandConnection* connection); @@ -307,15 +319,15 @@ class WaylandWindow : public PlatformWindow, // Stores current opacity of the window. Set on ::Initialize call. ui::PlatformWindowOpacity opacity_; - // For top level window, stores IDs of outputs that the window is currently - // rendered at. + // For top level window, stores outputs that the window is currently rendered + // at. // // Not used by popups. When sub-menus are hidden and shown again, Wayland // 'repositions' them to wrong outputs by sending them leave and enter // events so their list of entered outputs becomes meaningless after they have // been hidden at least once. To determine which output the popup belongs to, // we ask its parent. - base::flat_set entered_outputs_ids_; + std::vector entered_outputs_; // The type of the current WaylandWindow object. ui::PlatformWindowType type_ = ui::PlatformWindowType::kWindow; @@ -336,6 +348,8 @@ class WaylandWindow : public PlatformWindow, base::OnceClosure drag_loop_quit_closure_; + scoped_refptr ui_task_runner_; + base::WeakPtrFactory weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(WaylandWindow); 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 79f66eb7db1..b145ebefcc1 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 @@ -17,6 +17,7 @@ #include "ui/events/event.h" #include "ui/events/types/event_type.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/wayland/host/wayland_data_device.h" #include "ui/ozone/platform/wayland/host/wayland_screen.h" @@ -209,10 +210,10 @@ TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) { }); EXPECT_CALL(delegate_, OnBoundsChanged(_)) - .WillOnce([&](const gfx::Rect& bounds) { + .WillOnce([&](const PlatformWindowDelegate::BoundsChange& bounds) { EXPECT_EQ(State::kDetached, drag_controller()->state()); EXPECT_EQ(kDragging, test_step); - EXPECT_EQ(gfx::Point(20, 20), bounds.origin()); + EXPECT_EQ(gfx::Point(20, 20), bounds.bounds.origin()); SendDndDrop(); test_step = kDropping; @@ -299,10 +300,10 @@ TEST_P(WaylandWindowDragControllerTest, DragExitWindowAndDrop) { }); EXPECT_CALL(delegate_, OnBoundsChanged(_)) - .WillOnce([&](const gfx::Rect& bounds) { + .WillOnce([&](const PlatformWindowDelegate::BoundsChange& bounds) { EXPECT_EQ(State::kDetached, drag_controller()->state()); EXPECT_EQ(kDragging, test_step); - EXPECT_EQ(gfx::Point(20, 20), bounds.origin()); + EXPECT_EQ(gfx::Point(20, 20), bounds.bounds.origin()); SendDndLeave(); SendDndDrop(); @@ -407,10 +408,10 @@ TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop) { }); EXPECT_CALL(delegate_, OnBoundsChanged(_)) - .WillOnce([&](const gfx::Rect& bounds) { + .WillOnce([&](const PlatformWindowDelegate::BoundsChange& bounds) { EXPECT_EQ(State::kDetached, drag_controller()->state()); EXPECT_EQ(kDragging, test_step); - EXPECT_EQ(gfx::Point(50, 50), bounds.origin()); + EXPECT_EQ(gfx::Point(50, 50), bounds.bounds.origin()); // Exit |source_window| and enter the |target_window|. SendDndLeave(); @@ -529,7 +530,7 @@ TEST_P(WaylandWindowDragControllerTest, RestoreDuringWindowDragSession) { wl::ScopedWlArray states({XDG_TOPLEVEL_STATE_ACTIVATED}); // Maximize and check restored bounds is correctly set. - const gfx::Rect maximized_bounds = gfx::Rect(0, 0, 1024, 768); + gfx::Rect maximized_bounds = {0, 0, 1024, 768}; EXPECT_CALL(delegate_, OnBoundsChanged(testing::Eq(maximized_bounds))); window_->Maximize(); states.AddStateToWlArray(XDG_TOPLEVEL_STATE_MAXIMIZED); @@ -633,10 +634,10 @@ TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) { }); EXPECT_CALL(delegate_, OnBoundsChanged(_)) - .WillOnce([&](const gfx::Rect& bounds) { + .WillOnce([&](const PlatformWindowDelegate::BoundsChange& bounds) { EXPECT_EQ(State::kDetached, drag_controller()->state()); EXPECT_EQ(kDragging, test_step); - EXPECT_EQ(gfx::Point(100, 100), bounds.origin()); + EXPECT_EQ(gfx::Point(100, 100), bounds.bounds.origin()); // Send a few wl_pointer::motion events skipping sync and dispatch // checks, which will be done at |kDropping| test step handling. 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 90f2b76a2b0..d350c231ed9 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_factory.cc @@ -5,6 +5,7 @@ #include #include "base/compiler_specific.h" +#include "base/logging.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/wayland/host/wayland_auxiliary_window.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" @@ -15,6 +16,15 @@ namespace ui { +namespace { + +WaylandWindow* GetParentWindow(WaylandConnection* connection, + gfx::AcceleratedWidget widget) { + return connection->wayland_window_manager()->FindParentForNewWindow(widget); +} + +} // namespace + // static std::unique_ptr WaylandWindow::Create( PlatformWindowDelegate* delegate, @@ -26,10 +36,13 @@ std::unique_ptr WaylandWindow::Create( if (connection->IsDragInProgress()) { // We are in the process of drag and requested a popup. Most probably, // it is an arrow window. - window = std::make_unique(delegate, connection); + window = std::make_unique( + delegate, connection, + GetParentWindow(connection, properties.parent_widget)); break; } - FALLTHROUGH; + window = std::make_unique(delegate, connection); + break; 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() @@ -40,18 +53,18 @@ std::unique_ptr WaylandWindow::Create( // another by WaylandPopup) is a bad practice, and the parent window is // set here instead. TODO(crbug.com/1078328): Feed ozone/wayland with full // layout info required to properly position popup windows. - if (auto* parent_window = - connection->wayland_window_manager()->FindParentForNewWindow( - properties.parent_widget)) { - window = std::make_unique(delegate, connection); - window->set_parent_window(parent_window); + if (auto* parent = + GetParentWindow(connection, properties.parent_widget)) { + window = std::make_unique(delegate, connection, parent); } else { DLOG(WARNING) << "Failed to determine for menu/popup window."; window = std::make_unique(delegate, connection); } break; case PlatformWindowType::kTooltip: - window = std::make_unique(delegate, connection); + window = std::make_unique( + delegate, connection, + GetParentWindow(connection, properties.parent_widget)); break; case PlatformWindowType::kWindow: case PlatformWindowType::kBubble: diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc index ac1549a20a8..135b5face6c 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc @@ -117,7 +117,7 @@ std::vector WaylandWindowManager::GetWindowsOnOutput( uint32_t output_id) { std::vector result; for (auto entry : window_map_) { - if (entry.second->entered_outputs_ids().count(output_id) > 0) + if (entry.second->GetPreferredEnteredOutputId() == output_id) result.push_back(entry.second); } return result; 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 8237298cde9..64ee858d400 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 @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "testing/gtest/include/gtest/gtest.h" +#include "ui/ozone/platform/wayland/host/wayland_output.h" #include "ui/ozone/platform/wayland/test/mock_pointer.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/test_keyboard.h" @@ -184,10 +185,10 @@ TEST_P(WaylandWindowManagerTest, GetWindowsOnOutput) { Sync(); - auto entered_outputs_window1 = window1->entered_outputs_ids(); + auto entered_outputs_window1 = window1->entered_outputs(); EXPECT_EQ(1u, entered_outputs_window1.size()); - uint32_t output_id = *entered_outputs_window1.begin(); + uint32_t output_id = (*entered_outputs_window1.begin())->output_id(); auto windows_on_output = manager_->GetWindowsOnOutput(output_id); EXPECT_EQ(1u, windows_on_output.size()); 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 f6be452b0a1..dd3f1d97c0c 100644 --- a/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc @@ -29,6 +29,7 @@ #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" +#include "ui/ozone/platform/wayland/host/wayland_output.h" #include "ui/ozone/platform/wayland/host/wayland_subsurface.h" #include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h" #include "ui/ozone/platform/wayland/test/mock_pointer.h" @@ -134,7 +135,7 @@ class WaylandWindowTest : public WaylandTest { protected: void SendConfigureEventPopup(WaylandWindow* menu_window, const gfx::Rect bounds) { - auto* popup = GetPopupByWindow(menu_window); + auto* popup = GetTextXdgPopupByWindow(menu_window); ASSERT_TRUE(popup); if (GetParam() == kXdgShellV6) { zxdg_popup_v6_send_configure(popup->resource(), bounds.x(), bounds.y(), @@ -208,7 +209,7 @@ class WaylandWindowTest : public WaylandTest { void VerifyXdgPopupPosition(WaylandWindow* menu_window, const PopupPosition& position) { - auto* popup = GetPopupByWindow(menu_window); + auto* popup = GetTextXdgPopupByWindow(menu_window); ASSERT_TRUE(popup); EXPECT_EQ(popup->anchor_rect(), position.anchor_rect); @@ -249,7 +250,7 @@ class WaylandWindowTest : public WaylandTest { EXPECT_FALSE(window->CanDispatchEvent(&test_key_event)); } - wl::TestXdgPopup* GetPopupByWindow(WaylandWindow* window) { + wl::TestXdgPopup* GetTextXdgPopupByWindow(WaylandWindow* window) { wl::MockSurface* mock_surface = server_.GetObject( window->root_surface()->GetSurfaceId()); if (mock_surface) { @@ -270,7 +271,7 @@ class WaylandWindowTest : public WaylandTest { TEST_P(WaylandWindowTest, SetTitle) { EXPECT_CALL(*GetXdgToplevel(), SetTitle(StrEq("hello"))); - window_->SetTitle(base::ASCIIToUTF16("hello")); + window_->SetTitle(u"hello"); } TEST_P(WaylandWindowTest, UpdateVisualSizeConfiguresWaylandWindow) { @@ -285,7 +286,7 @@ TEST_P(WaylandWindowTest, UpdateVisualSizeConfiguresWaylandWindow) { // Configure event makes Wayland update bounds, but does not change toplevel // input region, opaque region or window geometry immediately. Such actions // are postponed to UpdateVisualSize(); - EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kNormalBounds))); EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds.width(), kNormalBounds.height())) .Times(0); @@ -420,7 +421,7 @@ TEST_P(WaylandWindowTest, MaximizeAndRestore) { uint32_t serial = 0; // Make sure the window has normal state initially. - EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kNormalBounds))); window_->SetBounds(kNormalBounds); EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState()); VerifyAndClearExpectations(); @@ -437,7 +438,7 @@ TEST_P(WaylandWindowTest, MaximizeAndRestore) { EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kMaximizedBounds.width(), kMaximizedBounds.height())); EXPECT_CALL(delegate_, OnActivationChanged(Eq(true))); - EXPECT_CALL(delegate_, OnBoundsChanged(kMaximizedBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kMaximizedBounds))); EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(1); window_->Maximize(); SendConfigureEvent(xdg_surface_, kMaximizedBounds.width(), @@ -471,7 +472,7 @@ TEST_P(WaylandWindowTest, MaximizeAndRestore) { kNormalBounds.height())); EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(1); EXPECT_CALL(delegate_, OnActivationChanged(_)).Times(0); - EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kNormalBounds))); EXPECT_CALL(*GetXdgToplevel(), UnsetMaximized()); window_->Restore(); // Reinitialize wl_array, which removes previous old states. @@ -731,7 +732,7 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { uint32_t serial = 0; // Make sure the window has normal state initially. - EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kNormalBounds))); window_->SetBounds(kNormalBounds); EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState()); VerifyAndClearExpectations(); @@ -747,7 +748,7 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kMaximizedBounds.width(), kMaximizedBounds.height())); EXPECT_CALL(delegate_, OnActivationChanged(Eq(true))); - EXPECT_CALL(delegate_, OnBoundsChanged(kMaximizedBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kMaximizedBounds))); EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(1); window_->Maximize(); // State changes are synchronous. @@ -782,7 +783,7 @@ TEST_P(WaylandWindowTest, SetMaximizedFullscreenAndRestore) { EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds.width(), kNormalBounds.height())); EXPECT_CALL(*GetXdgToplevel(), UnsetFullscreen()); - EXPECT_CALL(delegate_, OnBoundsChanged(kNormalBounds)); + EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kNormalBounds))); EXPECT_CALL(delegate_, OnWindowStateChanged(_)).Times(1); window_->Restore(); EXPECT_EQ(PlatformWindowState::kNormal, window_->GetPlatformWindowState()); @@ -1057,8 +1058,9 @@ TEST_P(WaylandWindowTest, SetCursorCallsZcrCursorShapesOncePerCursor) { TEST_P(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForNoneCursor) { MockZcrCursorShapes* mock_cursor_shapes = InstallMockZcrCursorShapes(); EXPECT_CALL(*mock_cursor_shapes, SetCursorShape(_)).Times(0); - // The "none" cursor is represented by nullptr. - window_->SetCursor(nullptr); + auto none_cursor = + base::MakeRefCounted(mojom::CursorType::kNone); + window_->SetCursor(none_cursor.get()); } TEST_P(WaylandWindowTest, SetCursorDoesNotUseZcrCursorShapesForCustomCursors) { @@ -1687,6 +1689,200 @@ TEST_P(WaylandWindowTest, AuxiliaryWindowUpdateBufferScale) { window_->SetPointerFocus(false); } +// Tests that a WaylandWindow uses the entered output with largest scale +// factor as the preferred output. If scale factors are equal, the very first +// entered display is used. +TEST_P(WaylandWindowTest, GetPreferredOutput) { + VerifyAndClearExpectations(); + + // Buffer scale must be 1 when no output has been entered by the window. + EXPECT_EQ(1, window_->buffer_scale()); + + // Creating an output with scale 1. + wl::TestOutput* output1 = server_.CreateAndInitializeOutput(); + output1->SetRect(gfx::Rect(0, 0, 1920, 1080)); + Sync(); + + // Creating an output with scale 2. + wl::TestOutput* output2 = server_.CreateAndInitializeOutput(); + output2->SetRect(gfx::Rect(1921, 0, 1920, 1080)); + Sync(); + + auto entered_outputs = window_->entered_outputs(); + EXPECT_EQ(0u, entered_outputs.size()); + + // Send the window to |output1|. + wl::MockSurface* surface = server_.GetObject( + window_->root_surface()->GetSurfaceId()); + ASSERT_TRUE(surface); + wl_surface_send_enter(surface->resource(), output1->resource()); + wl_surface_send_enter(surface->resource(), output2->resource()); + Sync(); + + // The window entered two outputs. + entered_outputs = window_->entered_outputs(); + EXPECT_EQ(2u, entered_outputs.size()); + + // The window must prefer the output that it entered first. + auto* expected_entered_output = *entered_outputs.begin(); + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); + + // Create the third output and pretend the window entered 3 outputs at the + // same time. + wl::TestOutput* output3 = server_.CreateAndInitializeOutput(); + output3->SetRect(gfx::Rect(0, 1081, 1920, 1080)); + Sync(); + + wl_surface_send_enter(surface->resource(), output3->resource()); + Sync(); + + // The window entered three outputs... + entered_outputs = window_->entered_outputs(); + EXPECT_EQ(3u, entered_outputs.size()); + + // but it still must prefer the output that it entered first. + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); + + // Pretend that the output2 has scale factor equals to 2 now. + output2->SetScale(2); + output2->Flush(); + Sync(); + + entered_outputs = window_->entered_outputs(); + EXPECT_EQ(3u, entered_outputs.size()); + + // It must be the second entered output now. + expected_entered_output = *(++entered_outputs.begin()); + EXPECT_EQ(2, expected_entered_output->scale_factor()); + + // The window_ must return the output with largest scale. + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); + + // Now, the output1 changes its scale factor to 2 as well. + output1->SetScale(2); + output1->Flush(); + Sync(); + + // It must be the very first output now. + entered_outputs = window_->entered_outputs(); + expected_entered_output = *entered_outputs.begin(); + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); + + // Now, the output1 changes its scale factor back to 1. + output1->SetScale(1); + output1->Flush(); + Sync(); + + // It must be the very the second output now. + entered_outputs = window_->entered_outputs(); + expected_entered_output = *(++entered_outputs.begin()); + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); + + // All outputs have scale factor of 1. window_ prefers the output that + // it entered first again. + output2->SetScale(1); + output2->Flush(); + Sync(); + + entered_outputs = window_->entered_outputs(); + expected_entered_output = *(entered_outputs.begin()); + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); +} + +TEST_P(WaylandWindowTest, GetChildrenPreferredOutput) { + VerifyAndClearExpectations(); + + // Buffer scale must be 1 when no output has been entered by the window. + EXPECT_EQ(1, window_->buffer_scale()); + + MockPlatformWindowDelegate menu_window_delegate; + std::unique_ptr menu_window = CreateWaylandWindowWithParams( + PlatformWindowType::kMenu, window_->GetWidget(), + gfx::Rect(10, 10, 10, 10), &menu_window_delegate); + + menu_window->Show(false); + + Sync(); + + // Creating an output with scale 1. + wl::TestOutput* output1 = server_.CreateAndInitializeOutput(); + output1->SetRect(gfx::Rect(0, 0, 1920, 1080)); + Sync(); + + // Creating an output with scale 2. + wl::TestOutput* output2 = server_.CreateAndInitializeOutput(); + output2->SetRect(gfx::Rect(1921, 0, 1920, 1080)); + Sync(); + + auto entered_outputs = window_->entered_outputs(); + EXPECT_EQ(0u, entered_outputs.size()); + + auto menu_entered_outputs = menu_window->entered_outputs(); + EXPECT_EQ(0u, menu_entered_outputs.size()); + + // Enter |output1|. + wl::MockSurface* surface = server_.GetObject( + window_->root_surface()->GetSurfaceId()); + ASSERT_TRUE(surface); + wl_surface_send_enter(surface->resource(), output1->resource()); + Sync(); + + // The window entered the output. + entered_outputs = window_->entered_outputs(); + EXPECT_EQ(1u, entered_outputs.size()); + + // The menu also things it entered the same output. + menu_entered_outputs = menu_window->entered_outputs(); + EXPECT_EQ(0u, menu_entered_outputs.size()); + + EXPECT_EQ(window_->GetPreferredEnteredOutputId(), + menu_window->GetPreferredEnteredOutputId()); + + // Pretend Wayland sends that menu entered output2, while the toplevel is on + // output1. Output1 must still be preferred by the menu. + wl::MockSurface* menu_surface = server_.GetObject( + menu_window->root_surface()->GetSurfaceId()); + wl_surface_send_enter(menu_surface->resource(), output1->resource()); + Sync(); + + // Nothing should have been changed here. + EXPECT_EQ(1u, window_->entered_outputs().size()); + EXPECT_EQ(0u, menu_window->entered_outputs().size()); + + EXPECT_EQ(window_->GetPreferredEnteredOutputId(), + menu_window->GetPreferredEnteredOutputId()); + + // Pretend Wayland sends that toplevel entered output2. + wl_surface_send_enter(surface->resource(), output1->resource()); + Sync(); + + EXPECT_EQ(2u, window_->entered_outputs().size()); + EXPECT_EQ(0u, menu_window->entered_outputs().size()); + + EXPECT_EQ(window_->GetPreferredEnteredOutputId(), + menu_window->GetPreferredEnteredOutputId()); + + // Now, the output2 changes its scale factor to 2. + output2->SetScale(2); + output2->Flush(); + Sync(); + + // It must be the very the second output now. + entered_outputs = window_->entered_outputs(); + auto* expected_entered_output = *(++entered_outputs.begin()); + EXPECT_EQ(expected_entered_output->output_id(), + window_->GetPreferredEnteredOutputId()); + + EXPECT_EQ(window_->GetPreferredEnteredOutputId(), + menu_window->GetPreferredEnteredOutputId()); +} + // Tests WaylandWindow repositions menu windows to be relative to parent window // in a right way. TEST_P(WaylandWindowTest, AdjustPopupBounds) { @@ -1781,9 +1977,9 @@ TEST_P(WaylandWindowTest, AdjustPopupBounds) { // bounds from relative to parent to be relative to screen. The Wayland // compositor does not reposition the menu, because it fits the screen, but // the nested menu window is repositioned to the left. - EXPECT_CALL( - nested_menu_window_delegate, - OnBoundsChanged(gfx::Rect({139, 156}, nested_menu_window_bounds.size()))); + EXPECT_CALL(nested_menu_window_delegate, + OnBoundsChanged( + Eq(gfx::Rect({139, 156}, nested_menu_window_bounds.size())))); calculated_nested_bounds.set_origin({-301, 80}); SendConfigureEventPopup(nested_menu_window.get(), calculated_nested_bounds); @@ -1796,10 +1992,12 @@ TEST_P(WaylandWindowTest, AdjustPopupBounds) { // menu window along y-axis and fixes bounds of a top level window so that it // is located (from the Chromium point of view) below origin of the menu // window. - EXPECT_CALL(delegate_, OnBoundsChanged( - gfx::Rect({0, 363}, window_->GetBounds().size()))); - EXPECT_CALL(menu_window_delegate, - OnBoundsChanged(gfx::Rect({440, 0}, menu_window_bounds.size()))); + EXPECT_CALL( + delegate_, + OnBoundsChanged(Eq(gfx::Rect({0, 363}, window_->GetBounds().size())))); + EXPECT_CALL( + menu_window_delegate, + OnBoundsChanged(Eq(gfx::Rect({440, 0}, menu_window_bounds.size())))); SendConfigureEventPopup(menu_window.get(), gfx::Rect({440, -363}, menu_window_bounds.size())); @@ -1837,9 +2035,9 @@ TEST_P(WaylandWindowTest, AdjustPopupBounds) { // bounds back to be relative to display correctly. If the window is near to // the left edge of a display, nothing is going to change, and the origin will // be the same as in the previous case. - EXPECT_CALL( - nested_menu_window_delegate, - OnBoundsChanged(gfx::Rect({149, 258}, nested_menu_window_bounds.size()))); + EXPECT_CALL(nested_menu_window_delegate, + OnBoundsChanged( + Eq(gfx::Rect({149, 258}, nested_menu_window_bounds.size())))); calculated_nested_bounds.set_origin({-291, 258}); SendConfigureEventPopup(nested_menu_window.get(), calculated_nested_bounds); @@ -1850,10 +2048,12 @@ TEST_P(WaylandWindowTest, AdjustPopupBounds) { // the WaylandWindow repositions the top level window back to 0,0 (which had // an offset to compensate the position of the menu window fliped along // y-axis. It just has had negative y value, which is wrong for Chromium. - EXPECT_CALL(delegate_, - OnBoundsChanged(gfx::Rect({0, 0}, window_->GetBounds().size()))); - EXPECT_CALL(menu_window_delegate, - OnBoundsChanged(gfx::Rect({440, 76}, menu_window_bounds.size()))); + EXPECT_CALL( + delegate_, + OnBoundsChanged(Eq(gfx::Rect({0, 0}, window_->GetBounds().size())))); + EXPECT_CALL( + menu_window_delegate, + OnBoundsChanged(Eq(gfx::Rect({440, 76}, menu_window_bounds.size())))); SendConfigureEventPopup(menu_window.get(), gfx::Rect({440, 76}, menu_window_bounds.size())); @@ -1947,7 +2147,7 @@ TEST_P(WaylandWindowTest, AuxiliaryWindowSimpleParent) { // Case 1: When the menu bounds are positive and there is a positive, // non-zero anchor width -TEST_P(WaylandWindowTest, NestedPopupMenu) { +TEST_P(WaylandWindowTest, NestedMenuWindows) { VerifyAndClearExpectations(); gfx::Rect menu_window_bounds(gfx::Rect(4, 20, 8, 20)); @@ -1958,32 +2158,33 @@ TEST_P(WaylandWindowTest, NestedPopupMenu) { VerifyAndClearExpectations(); - gfx::Rect nestedPopup_bounds(gfx::Rect(10, 30, 40, 20)); - std::unique_ptr nested_popup_window = - CreateWaylandWindowWithParams(PlatformWindowType::kPopup, + gfx::Rect nested_menu_bounds(gfx::Rect(10, 30, 40, 20)); + std::unique_ptr nested_menu_window = + CreateWaylandWindowWithParams(PlatformWindowType::kMenu, menu_window->GetWidget(), - nestedPopup_bounds, &delegate_); - EXPECT_TRUE(nested_popup_window); + nested_menu_bounds, &delegate_); + EXPECT_TRUE(nested_menu_window); VerifyAndClearExpectations(); - nested_popup_window->SetPointerFocus(true); + nested_menu_window->SetPointerFocus(true); Sync(); - auto* mock_surface_nested_popup = GetPopupByWindow(nested_popup_window.get()); + auto* mock_surface_nested_menu = + GetTextXdgPopupByWindow(nested_menu_window.get()); - ASSERT_TRUE(mock_surface_nested_popup); + ASSERT_TRUE(mock_surface_nested_menu); - auto anchor_width = (mock_surface_nested_popup->anchor_rect()).width(); + auto anchor_width = (mock_surface_nested_menu->anchor_rect()).width(); EXPECT_EQ(4, anchor_width); - nested_popup_window->SetPointerFocus(false); + nested_menu_window->SetPointerFocus(false); } // Case 2: When the menu bounds are positive and there is a negative or // zero anchor width -TEST_P(WaylandWindowTest, NestedPopupMenu1) { +TEST_P(WaylandWindowTest, NestedMenuWindows1) { VerifyAndClearExpectations(); gfx::Rect menu_window_bounds(gfx::Rect(6, 20, 8, 20)); @@ -1994,32 +2195,33 @@ TEST_P(WaylandWindowTest, NestedPopupMenu1) { VerifyAndClearExpectations(); - gfx::Rect nestedPopup_bounds(gfx::Rect(10, 30, 10, 20)); - std::unique_ptr nested_popup_window = - CreateWaylandWindowWithParams(PlatformWindowType::kPopup, + gfx::Rect nested_menu_bounds(gfx::Rect(10, 30, 10, 20)); + std::unique_ptr nested_menu_window = + CreateWaylandWindowWithParams(PlatformWindowType::kMenu, menu_window->GetWidget(), - nestedPopup_bounds, &delegate_); - EXPECT_TRUE(nested_popup_window); + nested_menu_bounds, &delegate_); + EXPECT_TRUE(nested_menu_window); VerifyAndClearExpectations(); - nested_popup_window->SetPointerFocus(true); + nested_menu_window->SetPointerFocus(true); Sync(); - auto* mock_surface_nested_popup = GetPopupByWindow(nested_popup_window.get()); + auto* mock_surface_nested_menu = + GetTextXdgPopupByWindow(nested_menu_window.get()); - ASSERT_TRUE(mock_surface_nested_popup); + ASSERT_TRUE(mock_surface_nested_menu); - auto anchor_width = (mock_surface_nested_popup->anchor_rect()).width(); + auto anchor_width = (mock_surface_nested_menu->anchor_rect()).width(); EXPECT_EQ(1, anchor_width); - nested_popup_window->SetPointerFocus(false); + nested_menu_window->SetPointerFocus(false); } // Case 3: When the menu bounds are negative and there is a positive, // non-zero anchor width -TEST_P(WaylandWindowTest, NestedPopupMenu2) { +TEST_P(WaylandWindowTest, NestedMenuWindows2) { VerifyAndClearExpectations(); gfx::Rect menu_window_bounds(gfx::Rect(10, 20, 40, 20)); @@ -2030,32 +2232,33 @@ TEST_P(WaylandWindowTest, NestedPopupMenu2) { VerifyAndClearExpectations(); - gfx::Rect nestedPopup_bounds(gfx::Rect(5, 30, 21, 20)); - std::unique_ptr nested_popup_window = - CreateWaylandWindowWithParams(PlatformWindowType::kPopup, + gfx::Rect nested_menu_bounds(gfx::Rect(5, 30, 21, 20)); + std::unique_ptr nested_menu_window = + CreateWaylandWindowWithParams(PlatformWindowType::kMenu, menu_window->GetWidget(), - nestedPopup_bounds, &delegate_); - EXPECT_TRUE(nested_popup_window); + nested_menu_bounds, &delegate_); + EXPECT_TRUE(nested_menu_window); VerifyAndClearExpectations(); - nested_popup_window->SetPointerFocus(true); + nested_menu_window->SetPointerFocus(true); Sync(); - auto* mock_surface_nested_popup = GetPopupByWindow(nested_popup_window.get()); + auto* mock_surface_nested_menu = + GetTextXdgPopupByWindow(nested_menu_window.get()); - ASSERT_TRUE(mock_surface_nested_popup); + ASSERT_TRUE(mock_surface_nested_menu); - auto anchor_width = (mock_surface_nested_popup->anchor_rect()).width(); + auto anchor_width = (mock_surface_nested_menu->anchor_rect()).width(); EXPECT_EQ(8, anchor_width); - nested_popup_window->SetPointerFocus(false); + nested_menu_window->SetPointerFocus(false); } // Case 4: When the menu bounds are negative and there is a negative, // zero anchor width -TEST_P(WaylandWindowTest, NestedPopupMenu3) { +TEST_P(WaylandWindowTest, NestedMenuWindows3) { VerifyAndClearExpectations(); gfx::Rect menu_window_bounds(gfx::Rect(10, 20, 20, 20)); @@ -2066,28 +2269,29 @@ TEST_P(WaylandWindowTest, NestedPopupMenu3) { VerifyAndClearExpectations(); - gfx::Rect nestedPopup_bounds(gfx::Rect(5, 30, 21, 20)); - std::unique_ptr nested_popup_window = - CreateWaylandWindowWithParams(PlatformWindowType::kPopup, + gfx::Rect nested_menu_bounds(gfx::Rect(5, 30, 21, 20)); + std::unique_ptr nested_menu_window = + CreateWaylandWindowWithParams(PlatformWindowType::kMenu, menu_window->GetWidget(), - nestedPopup_bounds, &delegate_); - EXPECT_TRUE(nested_popup_window); + nested_menu_bounds, &delegate_); + EXPECT_TRUE(nested_menu_window); VerifyAndClearExpectations(); - nested_popup_window->SetPointerFocus(true); + nested_menu_window->SetPointerFocus(true); Sync(); - auto* mock_surface_nested_popup = GetPopupByWindow(nested_popup_window.get()); + auto* mock_surface_nested_menu = + GetTextXdgPopupByWindow(nested_menu_window.get()); - ASSERT_TRUE(mock_surface_nested_popup); + ASSERT_TRUE(mock_surface_nested_menu); - auto anchor_width = (mock_surface_nested_popup->anchor_rect()).width(); + auto anchor_width = (mock_surface_nested_menu->anchor_rect()).width(); EXPECT_EQ(1, anchor_width); - nested_popup_window->SetPointerFocus(false); + nested_menu_window->SetPointerFocus(false); } TEST_P(WaylandWindowTest, AuxiliaryWindowNestedParent) { @@ -2220,7 +2424,8 @@ TEST_P(WaylandWindowTest, RemovesReattachesBackgroundOnHideShow) { EXPECT_TRUE(connection_->buffer_manager_host()); auto interface_ptr = connection_->buffer_manager_host()->BindInterface(); - buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, false); + buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, true, + false); // Setup wl_buffers. constexpr uint32_t buffer_id1 = 1; @@ -2301,7 +2506,7 @@ TEST_P(WaylandWindowTest, RemovesReattachesBackgroundOnHideShow) { // size constraints remain the same. TEST_P(WaylandWindowTest, SetsPropertiesOnShow) { constexpr char kAppId[] = "wayland_test"; - const base::string16 kTitle(base::UTF8ToUTF16("WaylandWindowTest")); + const std::u16string kTitle(u"WaylandWindowTest"); PlatformWindowInitProperties properties; properties.bounds = gfx::Rect(0, 0, 100, 100); @@ -2405,7 +2610,7 @@ TEST_P(WaylandWindowTest, CreatesPopupOnButtonPressSerial) { Sync(); - auto* test_popup = GetPopupByWindow(popup.get()); + auto* test_popup = GetTextXdgPopupByWindow(popup.get()); ASSERT_TRUE(test_popup); EXPECT_NE(test_popup->grab_serial(), button_release_serial); EXPECT_EQ(test_popup->grab_serial(), button_press_serial); @@ -2449,7 +2654,7 @@ TEST_P(WaylandWindowTest, CreatesPopupOnTouchDownSerial) { Sync(); - auto* test_popup = GetPopupByWindow(popup.get()); + auto* test_popup = GetTextXdgPopupByWindow(popup.get()); ASSERT_TRUE(test_popup); // Touch events are the exception. We can't use the serial that was sent @@ -2470,7 +2675,7 @@ TEST_P(WaylandWindowTest, CreatesPopupOnTouchDownSerial) { Sync(); - test_popup = GetPopupByWindow(popup.get()); + test_popup = GetTextXdgPopupByWindow(popup.get()); ASSERT_TRUE(test_popup); EXPECT_EQ(test_popup->grab_serial(), touch_down_serial); @@ -2524,7 +2729,7 @@ TEST_P(WaylandWindowTest, DoesNotGrabPopupIfNoSeat) { Sync(); - auto* test_popup = GetPopupByWindow(popup.get()); + auto* test_popup = GetTextXdgPopupByWindow(popup.get()); ASSERT_TRUE(test_popup); EXPECT_EQ(test_popup->grab_serial(), 0u); } 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 696beda426d..fdf633a89ae 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 @@ -119,6 +119,10 @@ base::Optional WaylandZcrCursorShapes::ShapeFromType(CursorType type) { return ZCR_CURSOR_SHAPES_V1_CURSOR_SHAPE_TYPE_GRABBING; case CursorType::kMiddlePanningVertical: case CursorType::kMiddlePanningHorizontal: + case CursorType::kEastWestNoResize: + case CursorType::kNorthEastSouthWestNoResize: + case CursorType::kNorthSouthNoResize: + case CursorType::kNorthWestSouthEastNoResize: // Not supported by this API. return base::nullopt; case CursorType::kCustom: diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc index 852573ae6fc..15b33ac0d4f 100644 --- a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc +++ b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc @@ -6,6 +6,7 @@ #include +#include "base/logging.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" 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 c88eccfba82..b29e63c4dfe 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 @@ -10,7 +10,6 @@ #include #include -#include "base/strings/string16.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" namespace gfx { diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc index cd57c613a36..4be7f24a708 100644 --- a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +++ b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc @@ -8,6 +8,7 @@ #include #include +#include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/hit_test.h" #include "ui/ozone/platform/wayland/common/wayland_util.h" @@ -98,7 +99,7 @@ void XDGToplevelWrapperImpl::SurfaceResize(WaylandConnection* connection, wl::IdentifyDirection(*connection, hittest)); } -void XDGToplevelWrapperImpl::SetTitle(const base::string16& title) { +void XDGToplevelWrapperImpl::SetTitle(const std::u16string& title) { DCHECK(xdg_toplevel_); xdg_toplevel_set_title(xdg_toplevel_.get(), base::UTF16ToUTF8(title).c_str()); } 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 867a54dd79e..15d16f7a3b7 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 @@ -35,7 +35,7 @@ class XDGToplevelWrapperImpl : public ShellToplevelWrapper { void SetMinimized() override; void SurfaceMove(WaylandConnection* connection) override; void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void AckConfigure(uint32_t serial) override; void SetWindowGeometry(const gfx::Rect& bounds) override; void SetMinSize(int32_t width, int32_t height) override; diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h index b306a4d635d..db2eeca882a 100644 --- a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h +++ b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h @@ -7,9 +7,9 @@ #include +#include #include -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" @@ -77,7 +77,7 @@ class ZWPTextInputWrapper { virtual void HideInputPanel() = 0; virtual void SetCursorRect(const gfx::Rect& rect) = 0; - virtual void SetSurroundingText(const base::string16& text, + virtual void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) = 0; }; diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc index 456b19474f1..ed95f49c4f6 100644 --- a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc +++ b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc @@ -8,7 +8,6 @@ #include #include "base/memory/ptr_util.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "ui/gfx/range/range.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" @@ -80,7 +79,7 @@ void ZWPTextInputWrapperV1::SetCursorRect(const gfx::Rect& rect) { } void ZWPTextInputWrapperV1::SetSurroundingText( - const base::string16& text, + const std::u16string& text, const gfx::Range& selection_range) { static constexpr size_t kWaylandMessageDataMaxLength = 4000; const std::string text_utf8 = base::UTF16ToUTF8(text); diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h index 3dab46b961f..d1c15fa5558 100644 --- a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h +++ b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.h @@ -39,7 +39,7 @@ class ZWPTextInputWrapperV1 : public ZWPTextInputWrapper { void HideInputPanel() override; void SetCursorRect(const gfx::Rect& rect) override; - void SetSurroundingText(const base::string16& text, + void SetSurroundingText(const std::u16string& text, const gfx::Range& selection_range) override; private: diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc index 385638d528b..7ec62ebf710 100644 --- a/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc +++ b/chromium/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc @@ -6,6 +6,8 @@ #include +#include "base/logging.h" +#include "base/notreached.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" 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 8fa9a289b6b..4a36633996c 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 @@ -10,7 +10,6 @@ #include #include -#include "base/strings/string16.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" namespace gfx { diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc index ea31771a618..7ad2845e7ff 100644 --- a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc +++ b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc @@ -8,6 +8,7 @@ #include #include +#include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/hit_test.h" #include "ui/ozone/platform/wayland/common/wayland_util.h" @@ -95,7 +96,7 @@ void ZXDGToplevelV6WrapperImpl::SurfaceResize(WaylandConnection* connection, wl::IdentifyDirection(*connection, hittest)); } -void ZXDGToplevelV6WrapperImpl::SetTitle(const base::string16& title) { +void ZXDGToplevelV6WrapperImpl::SetTitle(const std::u16string& title) { DCHECK(zxdg_toplevel_v6_); zxdg_toplevel_v6_set_title(zxdg_toplevel_v6_.get(), base::UTF16ToUTF8(title).c_str()); diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h index 7727bfec007..47d173287e6 100644 --- a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h +++ b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h @@ -36,7 +36,7 @@ class ZXDGToplevelV6WrapperImpl : public ShellToplevelWrapper { void SetMinimized() override; void SurfaceMove(WaylandConnection* connection) override; void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void AckConfigure(uint32_t serial) override; void SetWindowGeometry(const gfx::Rect& bounds) override; void SetMinSize(int32_t width, int32_t height) override; diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc index b568018a8dc..f3269c19f0e 100644 --- a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc +++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc @@ -18,6 +18,7 @@ #include "ui/base/cursor/cursor_factory.h" #include "ui/base/ime/linux/input_method_auralinux.h" #include "ui/base/ui_base_features.h" +#include "ui/events/devices/device_data_manager.h" #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" #include "ui/gfx/linux/client_native_pixmap_dmabuf.h" #include "ui/gfx/native_widget_types.h" @@ -111,8 +112,7 @@ class OzonePlatformWayland : public OzonePlatform { // The WaylandConnection and the WaylandOutputManager must be created // before PlatformScreen. DCHECK(connection_ && connection_->wayland_output_manager()); - return connection_->wayland_output_manager()->CreateWaylandScreen( - connection_.get()); + return connection_->wayland_output_manager()->CreateWaylandScreen(); } PlatformClipboard* GetPlatformClipboard() override { @@ -157,6 +157,9 @@ class OzonePlatformWayland : public OzonePlatform { } void InitializeUI(const InitParams& args) override { + // Initialize DeviceDataManager early as devices are set during + // WaylandConnection::Initialize(). + DeviceDataManager::CreateInstance(); #if BUILDFLAG(USE_XKBCOMMON) keyboard_layout_engine_ = std::make_unique(xkb_evdev_code_converter_); @@ -236,6 +239,14 @@ class OzonePlatformWayland : public OzonePlatform { // toplevel windows, clients simply don't know their position on screens // and always assume they are located at some arbitrary position. properties->ignore_screen_bounds_for_menus = true; + // Wayland uses sub-surfaces to show tooltips, and sub-surfaces must be + // bound to their root surfaces always, but finding the correct root + // surface at the moment of creating the tooltip is not always possible + // due to how Wayland handles focus and activation. + // Therefore, the platform should be given a hint at the moment when the + // surface is initialised, where it is known for sure which root surface + // shows the tooltip. + properties->set_parent_for_non_top_level_windows = true; properties->app_modal_dialogs_use_event_blocker = true; // Primary planes can be transluscent due to underlay strategy. As a diff --git a/chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.cc b/chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.cc new file mode 100644 index 00000000000..5993f19a522 --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.cc @@ -0,0 +1,301 @@ +// 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/test/wayland_ozone_ui_controls_test_helper.h" + +#include + +#include "base/threading/thread_task_runner_handle.h" +#include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" +#include "ui/ozone/platform/wayland/emulate/wayland_input_emulate.h" + +namespace wl { + +namespace { + +using ui_controls::DOWN; +using ui_controls::LEFT; +using ui_controls::MIDDLE; +using ui_controls::MouseButton; +using ui_controls::RIGHT; +using ui_controls::UP; + +class WaylandGlobalEventWaiter : public WaylandInputEmulate::Observer { + public: + enum class WaylandEventType { + kMotion, + kButton, + kKey, + kUnknown, + }; + + static WaylandGlobalEventWaiter* Create(WaylandEventType event_type, + int button, + bool pressed, + base::OnceClosure closure, + WaylandInputEmulate* emulate) { + DCHECK_NE(event_type, WaylandEventType::kUnknown); + return closure.is_null() + ? nullptr + : new WaylandGlobalEventWaiter(event_type, button, pressed, + std::move(closure), emulate); + } + + static WaylandGlobalEventWaiter* Create(WaylandEventType event_type, + const gfx::Point& screen_point, + base::OnceClosure closure, + WaylandInputEmulate* emulate) { + DCHECK_NE(event_type, WaylandEventType::kUnknown); + return closure.is_null() + ? nullptr + : new WaylandGlobalEventWaiter(event_type, screen_point, + std::move(closure), emulate); + } + + private: + WaylandGlobalEventWaiter(WaylandEventType event_type, + const gfx::Point& screen_point, + base::OnceClosure closure, + WaylandInputEmulate* emulate) + : event_type_(event_type), + closure_(std::move(closure)), + emulate_(emulate), + screen_point_(screen_point) { + Initialize(); + } + + WaylandGlobalEventWaiter(WaylandEventType event_type, + int button, + bool pressed, + base::OnceClosure closure, + WaylandInputEmulate* emulate) + : event_type_(event_type), + closure_(std::move(closure)), + emulate_(emulate), + button_or_key_(button), + pressed_(pressed) { + Initialize(); + } + + ~WaylandGlobalEventWaiter() override { emulate_->RemoveObserver(this); } + + void Initialize() { + DCHECK_NE(event_type_, WaylandEventType::kUnknown); + DCHECK(!closure_.is_null()); + emulate_->AddObserver(this); + } + + void OnPointerMotionGlobal(const gfx::Point& screen_position) override { + if (event_type_ == WaylandEventType::kMotion) { + ExecuteClosure(); + } + } + + void OnPointerButtonGlobal(int32_t button, bool pressed) override { + if (event_type_ == WaylandEventType::kButton && button_or_key_ == button && + pressed == pressed_) { + ExecuteClosure(); + } + } + + void OnKeyboardKey(int32_t key, bool pressed) override { + if (event_type_ == WaylandEventType::kKey && button_or_key_ == key && + pressed == pressed_) { + ExecuteClosure(); + } + } + + void ExecuteClosure() { + DCHECK(!closure_.is_null()); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(closure_)); + delete this; + } + + // Expected event type. + WaylandEventType event_type_ = WaylandEventType::kUnknown; + + base::OnceClosure closure_; + + WaylandInputEmulate* const emulate_; + + // Expected pointer location on screen. + gfx::Point screen_point_; + + // Expected button or key. + int button_or_key_ = -1; + + // Expected key or button to be pressed or depressed. + bool pressed_ = false; +}; + +} // namespace + +WaylandOzoneUIControlsTestHelper::WaylandOzoneUIControlsTestHelper() + : input_emulate_(std::make_unique()) {} + +WaylandOzoneUIControlsTestHelper::~WaylandOzoneUIControlsTestHelper() = default; + +unsigned WaylandOzoneUIControlsTestHelper::ButtonDownMask() const { + return button_down_mask_; +} + +void WaylandOzoneUIControlsTestHelper::SendKeyPressEvent( + gfx::AcceleratedWidget widget, + ui::KeyboardCode key, + bool control, + bool shift, + bool alt, + bool command, + base::OnceClosure closure) { + SendKeyPressInternal(widget, key, control, shift, alt, command, {}, + true /* key press */); + SendKeyPressInternal(widget, key, control, shift, alt, command, + std::move(closure), false /* key release */); +} + +void WaylandOzoneUIControlsTestHelper::SendMouseMotionNotifyEvent( + gfx::AcceleratedWidget widget, + const gfx::Point& mouse_loc, + const gfx::Point& mouse_root_loc, + base::OnceClosure closure) { + WaylandGlobalEventWaiter::Create( + WaylandGlobalEventWaiter::WaylandEventType::kMotion, mouse_loc, + std::move(closure), input_emulate_.get()); + + input_emulate_->EmulatePointerMotion(widget, mouse_loc); +} + +void WaylandOzoneUIControlsTestHelper::SendMouseEvent( + gfx::AcceleratedWidget widget, + ui_controls::MouseButton type, + int button_state, + int accelerator_state, + const gfx::Point& mouse_loc, + const gfx::Point& mouse_root_loc, + base::OnceClosure closure) { + uint32_t changed_button = 0; + switch (type) { + case LEFT: + changed_button = BTN_LEFT; + break; + case MIDDLE: + changed_button = BTN_MIDDLE; + break; + case RIGHT: + changed_button = BTN_RIGHT; + break; + default: + NOTREACHED(); + } + + // Press accelerator keys. + if (accelerator_state) { + SendKeyPressInternal(widget, ui::KeyboardCode::VKEY_UNKNOWN, + accelerator_state & ui_controls::kControl, + accelerator_state & ui_controls::kShift, + accelerator_state & ui_controls::kAlt, + accelerator_state & ui_controls::kCommand, {}, true); + } + + SendMouseMotionNotifyEvent(widget, mouse_loc, mouse_root_loc, {}); + + WaylandGlobalEventWaiter::Create( + WaylandGlobalEventWaiter::WaylandEventType::kButton, changed_button, + button_state & UP, std::move(closure), input_emulate_.get()); + + if (button_state & DOWN) { + input_emulate_->EmulatePointerButton( + widget, ui::EventType::ET_MOUSE_PRESSED, changed_button); + button_down_mask_ |= changed_button; + } + if (button_state & UP) { + input_emulate_->EmulatePointerButton( + widget, ui::EventType::ET_MOUSE_RELEASED, changed_button); + button_down_mask_ = (button_down_mask_ | changed_button) ^ changed_button; + } + + // Depress accelerator keys. + if (accelerator_state) { + SendKeyPressInternal(widget, ui::KeyboardCode::VKEY_UNKNOWN, + accelerator_state & ui_controls::kControl, + accelerator_state & ui_controls::kShift, + accelerator_state & ui_controls::kAlt, + accelerator_state & ui_controls::kCommand, {}, false); + } +} + +void WaylandOzoneUIControlsTestHelper::RunClosureAfterAllPendingUIEvents( + base::OnceClosure closure) { + NOTREACHED(); +} + +bool WaylandOzoneUIControlsTestHelper::MustUseUiControlsForMoveCursorTo() { + return true; +} + +void WaylandOzoneUIControlsTestHelper::SendKeyPressInternal( + gfx::AcceleratedWidget widget, + ui::KeyboardCode key, + bool control, + bool shift, + bool alt, + bool command, + base::OnceClosure closure, + bool press_key) { + auto dom_code = UsLayoutKeyboardCodeToDomCode(key); + + WaylandGlobalEventWaiter::Create( + WaylandGlobalEventWaiter::WaylandEventType::kKey, + ui::KeycodeConverter::DomCodeToEvdevCode(dom_code), press_key, + std::move(closure), input_emulate_.get()); + + if (press_key) { + if (control) + DispatchKeyPress(widget, ui::EventType::ET_KEY_PRESSED, + ui::DomCode::CONTROL_LEFT); + + if (shift) + DispatchKeyPress(widget, ui::EventType::ET_KEY_PRESSED, + ui::DomCode::SHIFT_LEFT); + + if (alt) + DispatchKeyPress(widget, ui::EventType::ET_KEY_PRESSED, + ui::DomCode::ALT_LEFT); + + DispatchKeyPress(widget, ui::EventType::ET_KEY_PRESSED, dom_code); + } else { + DispatchKeyPress(widget, ui::EventType::ET_KEY_RELEASED, dom_code); + + if (alt) + DispatchKeyPress(widget, ui::EventType::ET_KEY_RELEASED, + ui::DomCode::ALT_LEFT); + + if (shift) + DispatchKeyPress(widget, ui::EventType::ET_KEY_RELEASED, + ui::DomCode::SHIFT_LEFT); + + if (control) + DispatchKeyPress(widget, ui::EventType::ET_KEY_RELEASED, + ui::DomCode::CONTROL_LEFT); + } +} + +void WaylandOzoneUIControlsTestHelper::DispatchKeyPress( + gfx::AcceleratedWidget widget, + ui::EventType event_type, + ui::DomCode dom_code) { + input_emulate_->EmulateKeyboardKey(widget, event_type, dom_code); +} + +} // namespace wl + +namespace ui { + +OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWayland() { + return new wl::WaylandOzoneUIControlsTestHelper(); +} + +} // namespace ui diff --git a/chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.h b/chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.h new file mode 100644 index 00000000000..e89aff57835 --- /dev/null +++ b/chromium/ui/ozone/platform/wayland/test/wayland_ozone_ui_controls_test_helper.h @@ -0,0 +1,74 @@ +// 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_TEST_WAYLAND_OZONE_UI_CONTROLS_TEST_HELPER_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_WAYLAND_OZONE_UI_CONTROLS_TEST_HELPER_H_ + +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/types/event_type.h" +#include "ui/ozone/public/ozone_ui_controls_test_helper.h" + +namespace wl { + +class WaylandInputEmulate; + +class WaylandOzoneUIControlsTestHelper : public ui::OzoneUIControlsTestHelper { + public: + WaylandOzoneUIControlsTestHelper(); + WaylandOzoneUIControlsTestHelper(const WaylandOzoneUIControlsTestHelper&) = + delete; + WaylandOzoneUIControlsTestHelper& operator=( + const WaylandOzoneUIControlsTestHelper&) = delete; + ~WaylandOzoneUIControlsTestHelper() override; + + unsigned ButtonDownMask() const override; + void SendKeyPressEvent(gfx::AcceleratedWidget widget, + ui::KeyboardCode key, + bool control, + bool shift, + bool alt, + bool command, + base::OnceClosure closure) override; + void SendMouseMotionNotifyEvent(gfx::AcceleratedWidget widget, + const gfx::Point& mouse_loc, + const gfx::Point& mouse_root_loc, + base::OnceClosure closure) override; + void SendMouseEvent(gfx::AcceleratedWidget widget, + ui_controls::MouseButton type, + int button_state, + int accelerator_state, + const gfx::Point& mouse_loc, + const gfx::Point& mouse_root_loc, + base::OnceClosure closure) override; + void RunClosureAfterAllPendingUIEvents(base::OnceClosure closure) override; + bool MustUseUiControlsForMoveCursorTo() override; + + private: + // Sends either press or release key based |press_key| value. + void SendKeyPressInternal(gfx::AcceleratedWidget widget, + ui::KeyboardCode key, + bool control, + bool shift, + bool alt, + bool command, + base::OnceClosure closure, + bool press_key); + void DispatchKeyPress(gfx::AcceleratedWidget widget, + ui::EventType event_type, + ui::DomCode key); + + unsigned button_down_mask_ = 0; + + std::unique_ptr input_emulate_; +}; + +} // namespace wl + +namespace ui { + +OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWayland(); + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_WAYLAND_OZONE_UI_CONTROLS_TEST_HELPER_H_ diff --git a/chromium/ui/ozone/platform/wayland/test/wayland_test.cc b/chromium/ui/ozone/platform/wayland/test/wayland_test.cc index b226e31dbc3..5bc45ac1aea 100644 --- a/chromium/ui/ozone/platform/wayland/test/wayland_test.cc +++ b/chromium/ui/ozone/platform/wayland/test/wayland_test.cc @@ -8,6 +8,7 @@ #include "base/run_loop.h" #include "ui/base/ui_base_features.h" +#include "ui/events/devices/device_data_manager.h" #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" @@ -58,10 +59,16 @@ void WaylandTest::SetUp() { {features::kUseOzonePlatform, ui::kWaylandOverlayDelegation}, {}); ASSERT_TRUE(features::IsUsingOzonePlatform()); + if (DeviceDataManager::HasInstance()) { + // Another instance may have already been set before. + DeviceDataManager::GetInstance()->ResetDeviceListsForTest(); + } else { + DeviceDataManager::CreateInstance(); + } + ASSERT_TRUE(server_.Start(GetParam())); ASSERT_TRUE(connection_->Initialize()); - screen_ = connection_->wayland_output_manager()->CreateWaylandScreen( - connection_.get()); + screen_ = connection_->wayland_output_manager()->CreateWaylandScreen(); EXPECT_CALL(delegate_, OnAcceleratedWidgetAvailable(_)) .WillOnce(SaveArg<0>(&widget_)); PlatformWindowInitProperties properties; @@ -89,6 +96,12 @@ void WaylandTest::SetUp() { Sync(); + EXPECT_EQ(0u, + DeviceDataManager::GetInstance()->GetTouchscreenDevices().size()); + EXPECT_EQ(0u, DeviceDataManager::GetInstance()->GetKeyboardDevices().size()); + EXPECT_EQ(0u, DeviceDataManager::GetInstance()->GetMouseDevices().size()); + EXPECT_EQ(0u, DeviceDataManager::GetInstance()->GetTouchpadDevices().size()); + initialized_ = true; } 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 a8767ae8265..77e58e1a6e9 100644 --- a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc +++ b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc @@ -84,7 +84,8 @@ class WaylandBufferManagerTest : public WaylandTest { // callback and bind the interface again if the manager failed. manager_host_->SetTerminateGpuCallback(callback_.Get()); auto interface_ptr = manager_host_->BindInterface(); - buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, false); + buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, true, + false); } protected: @@ -120,7 +121,7 @@ class WaylandBufferManagerTest : public WaylandTest { // same). buffer_manager_gpu_ = std::make_unique(); buffer_manager_gpu_->Initialize(std::move(interface_ptr), {}, false, - false); + true, false); })); } } @@ -1510,17 +1511,16 @@ TEST_P(WaylandBufferManagerTest, testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu); testing::Mock::VerifyAndClearExpectations(mock_surface); - // Now, commit the buffer with the |kBufferId2| again and make sure the - // manager manually sends the submission callback as long as the compositor is - // not going to release a buffer as it was the same buffer submitted more than - // once. + // Now, commit the buffer with the |kBufferId2| again. The manager does not + // 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)) .Times(1); EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1); EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(0); - EXPECT_CALL(*mock_surface, Frame(_)).Times(1); + EXPECT_CALL(*mock_surface, Frame(_)).Times(0); EXPECT_CALL(*mock_surface, DamageBuffer(0, 0, bounds.width(), bounds.height())) .Times(1); diff --git a/chromium/ui/ozone/platform/windows/windows_surface_factory.cc b/chromium/ui/ozone/platform/windows/windows_surface_factory.cc index 83b51fb2dba..0f5ca608adf 100644 --- a/chromium/ui/ozone/platform/windows/windows_surface_factory.cc +++ b/chromium/ui/ozone/platform/windows/windows_surface_factory.cc @@ -50,7 +50,8 @@ class GLOzoneEGLWindows : public GLOzoneEGL { return gl::EGLDisplayPlatform(GetWindowDC(nullptr)); } - bool LoadGLES2Bindings(gl::GLImplementation implementation) override { + bool LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) override { return LoadDefaultEGLGLES2Bindings(implementation); } @@ -72,8 +73,8 @@ WindowsSurfaceFactory::GetAllowedGLImplementations() { } GLOzone* WindowsSurfaceFactory::GetGLOzone( - gl::GLImplementation implementation) { - switch (implementation) { + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationSwiftShaderGL: case gl::kGLImplementationEGLGLES2: return egl_implementation_.get(); diff --git a/chromium/ui/ozone/platform/windows/windows_surface_factory.h b/chromium/ui/ozone/platform/windows/windows_surface_factory.h index 85f5c647095..645352d0f29 100644 --- a/chromium/ui/ozone/platform/windows/windows_surface_factory.h +++ b/chromium/ui/ozone/platform/windows/windows_surface_factory.h @@ -23,7 +23,7 @@ class WindowsSurfaceFactory : public SurfaceFactoryOzone { // SurfaceFactoryOzone: std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; private: std::unique_ptr egl_implementation_; diff --git a/chromium/ui/ozone/platform/x11/BUILD.gn b/chromium/ui/ozone/platform/x11/BUILD.gn index 7cf0bfdff6c..0d6c78ccd65 100644 --- a/chromium/ui/ozone/platform/x11/BUILD.gn +++ b/chromium/ui/ozone/platform/x11/BUILD.gn @@ -9,6 +9,8 @@ import("//ui/base/ui_features.gni") visibility = [ "//ui/ozone/*" ] +assert(is_linux || is_chromeos) + source_set("x11") { sources = [ "client_native_pixmap_factory_x11.cc", @@ -25,6 +27,8 @@ source_set("x11") { "x11_canvas_surface.h", "x11_clipboard_ozone.cc", "x11_clipboard_ozone.h", + "x11_global_shortcut_listener_ozone.cc", + "x11_global_shortcut_listener_ozone.h", "x11_menu_utils.cc", "x11_menu_utils.h", "x11_screen_ozone.cc", @@ -33,6 +37,8 @@ source_set("x11") { "x11_surface_factory.h", "x11_user_input_monitor.cc", "x11_user_input_monitor.h", + "x11_utils.cc", + "x11_utils.h", ] deps = [ diff --git a/chromium/ui/ozone/platform/x11/gl_ozone_glx.cc b/chromium/ui/ozone/platform/x11/gl_ozone_glx.cc index 5a6a63ee4cf..712a10f497d 100644 --- a/chromium/ui/ozone/platform/x11/gl_ozone_glx.cc +++ b/chromium/ui/ozone/platform/x11/gl_ozone_glx.cc @@ -32,7 +32,7 @@ bool GLOzoneGLX::InitializeGLOneOffPlatform() { } bool GLOzoneGLX::InitializeStaticGLBindings( - gl::GLImplementation implementation) { + const gl::GLImplementationParts& implementation) { base::NativeLibrary library = nullptr; const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); diff --git a/chromium/ui/ozone/platform/x11/gl_ozone_glx.h b/chromium/ui/ozone/platform/x11/gl_ozone_glx.h index 7af963f6a74..8bdbc018a3c 100644 --- a/chromium/ui/ozone/platform/x11/gl_ozone_glx.h +++ b/chromium/ui/ozone/platform/x11/gl_ozone_glx.h @@ -17,7 +17,8 @@ class GLOzoneGLX : public GLOzone { ~GLOzoneGLX() override {} bool InitializeGLOneOffPlatform() override; - bool InitializeStaticGLBindings(gl::GLImplementation implementation) override; + bool InitializeStaticGLBindings( + const gl::GLImplementationParts& implementation) override; void SetDisabledExtensionsPlatform( const std::string& disabled_extensions) override; bool InitializeExtensionSettingsOneOffPlatform() override; diff --git a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc index 455f238ac68..5a9ed84fc90 100644 --- a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc +++ b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc @@ -5,13 +5,14 @@ #include "ui/ozone/platform/x11/ozone_platform_x11.h" #include +#include #include +#include "base/command_line.h" #include "base/message_loop/message_pump_type.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" #include "build/build_config.h" @@ -30,13 +31,16 @@ #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/switches.h" #include "ui/ozone/common/stub_overlay_manager.h" #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_menu_utils.h" #include "ui/ozone/platform/x11/x11_screen_ozone.h" #include "ui/ozone/platform/x11/x11_surface_factory.h" #include "ui/ozone/platform/x11/x11_user_input_monitor.h" +#include "ui/ozone/platform/x11/x11_utils.h" #include "ui/ozone/public/gpu_platform_support_host.h" #include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/ozone_platform.h" @@ -107,7 +111,7 @@ class OzonePlatformX11 : public OzonePlatform, PlatformWindowInitProperties properties) override { auto window = std::make_unique(delegate); window->Initialize(std::move(properties)); - window->SetTitle(base::ASCIIToUTF16("Ozone X11")); + window->SetTitle(u"Ozone X11"); return std::move(window); } @@ -152,6 +156,17 @@ class OzonePlatformX11 : public OzonePlatform, return menu_utils_.get(); } + PlatformUtils* GetPlatformUtils() override { return x11_utils_.get(); } + + PlatformGlobalShortcutListener* GetPlatformGlobalShortcutListener( + PlatformGlobalShortcutListenerDelegate* delegate) override { + if (!global_shortcut_listener_) { + global_shortcut_listener_ = + std::make_unique(delegate); + } + return global_shortcut_listener_.get(); + } + std::unique_ptr CreateProvider() override { #if BUILDFLAG(IS_CHROMEOS_ASH) return std::make_unique(); @@ -196,6 +211,14 @@ class OzonePlatformX11 : public OzonePlatform, } void InitializeUI(const InitParams& params) override { + // If opening the connection failed there is nothing we can do. Crash here + // instead of crashing later. If you are crashing here, make sure there is + // an X server running and $DISPLAY is set. + // In case of non-Ozone/X11, the very same check happens during the + // BrowserMainLoop::InitializeToolkit call. + if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) + CHECK(x11::Connection::Get()->Ready()) << "Missing X server or $DISPLAY"; + InitializeCommon(params); CreatePlatformEventSource(); overlay_manager_ = std::make_unique(); @@ -225,6 +248,7 @@ class OzonePlatformX11 : public OzonePlatform, #endif menu_utils_ = std::make_unique(); + x11_utils_ = std::make_unique(); base::UmaHistogramEnumeration("Linux.WindowManager", GetWindowManagerUMA()); } @@ -271,11 +295,6 @@ class OzonePlatformX11 : public OzonePlatform, if (common_initialized_) return; - // If opening the connection failed there is nothing we can do. Crash here - // instead of crashing later. If you are crashing here, make sure there is - // an X server running and $DISPLAY is set. - CHECK(x11::Connection::Get()->Ready()) << "Missing X server or $DISPLAY"; - common_initialized_ = true; } @@ -302,6 +321,8 @@ class OzonePlatformX11 : public OzonePlatform, std::unique_ptr cursor_factory_; std::unique_ptr gpu_platform_support_host_; std::unique_ptr menu_utils_; + std::unique_ptr x11_utils_; + std::unique_ptr global_shortcut_listener_; // Objects in the GPU process. std::unique_ptr surface_factory_ozone_; diff --git a/chromium/ui/ozone/platform/x11/x11_canvas_surface.cc b/chromium/ui/ozone/platform/x11/x11_canvas_surface.cc index 7ece6c9954d..d4491354768 100644 --- a/chromium/ui/ozone/platform/x11/x11_canvas_surface.cc +++ b/chromium/ui/ozone/platform/x11/x11_canvas_surface.cc @@ -7,6 +7,8 @@ #include "base/bind.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImageInfo.h" +#include "ui/base/x/x11_display_util.h" +#include "ui/base/x/x11_xrandr_interval_only_vsync_provider.h" #include "ui/gfx/vsync_provider.h" #include "ui/gfx/x/connection.h" @@ -30,9 +32,7 @@ void X11CanvasSurface::PresentCanvas(const gfx::Rect& damage) { } std::unique_ptr X11CanvasSurface::CreateVSyncProvider() { - // TODO(https://crbug.com/1001498) - NOTIMPLEMENTED_LOG_ONCE(); - return nullptr; + return std::make_unique(); } bool X11CanvasSurface::SupportsAsyncBufferSwap() const { diff --git a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc index 5944973e00c..aee9ba9eabf 100644 --- a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc +++ b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.cc @@ -4,401 +4,69 @@ #include "ui/ozone/platform/x11/x11_clipboard_ozone.h" -#include +#include +#include #include -#include "base/containers/contains.h" -#include "base/containers/span.h" -#include "base/logging.h" +#include "base/bind.h" #include "ui/base/clipboard/clipboard_constants.h" -#include "ui/base/x/x11_util.h" -#include "ui/events/platform/x11/x11_event_source.h" -#include "ui/gfx/x/extension_manager.h" -#include "ui/gfx/x/x11_atom_cache.h" -#include "ui/gfx/x/xproto.h" -#include "ui/gfx/x/xproto_util.h" - -using base::Contains; +#include "ui/base/x/x11_clipboard_helper.h" namespace ui { -namespace { - -const char kChromeSelection[] = "CHROME_SELECTION"; -const char kClipboard[] = "CLIPBOARD"; -const char kTargets[] = "TARGETS"; -const char kTimestamp[] = "TIMESTAMP"; - -// Helps to allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING. -void ExpandTypes(std::vector* list) { - bool has_mime_type_text = Contains(*list, ui::kMimeTypeText); - bool has_string = Contains(*list, kMimeTypeLinuxString); - bool has_mime_type_utf8 = Contains(*list, kMimeTypeTextUtf8); - bool has_utf8_string = Contains(*list, kMimeTypeLinuxUtf8String); - if (has_mime_type_text && !has_string) - list->push_back(kMimeTypeLinuxString); - if (has_string && !has_mime_type_text) - list->push_back(ui::kMimeTypeText); - if (has_mime_type_utf8 && !has_utf8_string) - list->push_back(kMimeTypeLinuxUtf8String); - if (has_utf8_string && !has_mime_type_utf8) - list->push_back(kMimeTypeTextUtf8); -} - -} // namespace - -// Maintains state of a single selection (aka system clipboard buffer). -struct X11ClipboardOzone::SelectionState { - SelectionState() = default; - ~SelectionState() = default; - - // DataMap we keep from |OfferClipboardData| to service remote requests for - // the clipboard. - PlatformClipboard::DataMap offer_data_map; - - // DataMap from |RequestClipboardData| that we write remote clipboard - // contents to before calling the completion callback. - PlatformClipboard::DataMap* request_data_map = nullptr; - - // Mime types supported by remote clipboard. - std::vector mime_types; - - // Data most recently read from remote clipboard. - PlatformClipboard::Data data; - - // Mime type of most recently read data from remote clipboard. - std::string data_mime_type; - - // Callbacks are stored when we haven't already prefetched the remote - // clipboard. - PlatformClipboard::GetMimeTypesClosure get_available_mime_types_callback; - PlatformClipboard::RequestDataClosure request_clipboard_data_callback; - - // The time that this instance took ownership of the clipboard. - x11::Time acquired_selection_timestamp; -}; - X11ClipboardOzone::X11ClipboardOzone() - : atom_clipboard_(x11::GetAtom(kClipboard)), - atom_targets_(x11::GetAtom(kTargets)), - atom_timestamp_(x11::GetAtom(kTimestamp)), - x_property_(x11::GetAtom(kChromeSelection)), - connection_(x11::Connection::Get()), - x_window_(x11::CreateDummyWindow("Chromium Clipboard Window")) { - connection_->xfixes().QueryVersion( - {x11::XFixes::major_version, x11::XFixes::minor_version}); - if (!connection_->xfixes().present()) - return; - using_xfixes_ = true; - - // Register to receive standard X11 events. - connection_->AddEventObserver(this); - - for (auto atom : {atom_clipboard_, x11::Atom::PRIMARY}) { - // Register the selection state. - selection_state_.emplace(atom, std::make_unique()); - // Register to receive XFixes notification when selection owner changes. - connection_->xfixes().SelectSelectionInput( - {x_window_, atom, x11::XFixes::SelectionEventMask::SetSelectionOwner}); - // Prefetch the current remote clipboard contents. - QueryTargets(atom); - } -} - -X11ClipboardOzone::~X11ClipboardOzone() { - connection_->RemoveEventObserver(this); -} - -void X11ClipboardOzone::OnEvent(const x11::Event& xev) { - if (auto* request = xev.As()) { - if (request->owner == x_window_) - OnSelectionRequest(*request); - } else if (auto* notify = xev.As()) { - if (notify->requestor == x_window_) - OnSelectionNotify(*notify); - } else if (auto* notify = xev.As()) { - if (notify->window == x_window_) - OnSetSelectionOwnerNotify(*notify); - } -} - -// We are the clipboard owner, and a remote peer has requested either: -// TARGETS: List of mime types that we support for the clipboard. -// TIMESTAMP: Time when we took ownership of the clipboard. -// : Mime type to receive clipboard as. -void X11ClipboardOzone::OnSelectionRequest( - const x11::SelectionRequestEvent& event) { - // The property must be set. - if (event.property == x11::Atom::None) - return; - - // target=TARGETS. - auto& selection_state = - GetSelectionState(static_cast(event.selection)); - auto target = static_cast(event.target); - PlatformClipboard::DataMap& offer_data_map = selection_state.offer_data_map; - if (target == atom_targets_) { - std::vector targets; - // Add TIMESTAMP. - targets.push_back(kTimestamp); - for (auto& entry : offer_data_map) { - targets.push_back(entry.first); - } - // Expand types, then convert from string to atom. - ExpandTypes(&targets); - std::vector atoms; - for (auto& entry : targets) - atoms.push_back(x11::GetAtom(entry.c_str())); - SetArrayProperty(event.requestor, event.property, x11::Atom::ATOM, atoms); - - } else if (target == atom_timestamp_) { - // target=TIMESTAMP. - SetProperty(event.requestor, event.property, x11::Atom::INTEGER, - selection_state.acquired_selection_timestamp); - } else { - // Send clipboard data. - std::string target_name; - if (auto reply = connection_->GetAtomName({event.target}).Sync()) - target_name = std::move(reply->name); - - std::string key = target_name; - // Allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING. - if (key == kMimeTypeLinuxUtf8String && - !Contains(offer_data_map, kMimeTypeLinuxUtf8String)) { - key = kMimeTypeTextUtf8; - } else if (key == kMimeTypeLinuxString && - !Contains(offer_data_map, kMimeTypeLinuxString)) { - key = kMimeTypeText; - } - auto it = offer_data_map.find(key); - if (it != offer_data_map.end()) { - SetArrayProperty(event.requestor, event.property, event.target, - it->second->data()); - } - } - - // Notify remote peer that clipboard has been sent. - x11::SelectionNotifyEvent selection_event{ - .time = event.time, - .requestor = event.requestor, - .selection = event.selection, - .target = event.target, - .property = event.property, - }; - x11::SendEvent(selection_event, selection_event.requestor, - x11::EventMask::NoEvent); + : helper_(std::make_unique( + base::BindRepeating(&X11ClipboardOzone::OnSelectionChanged, + base::Unretained(this)))) { + DCHECK(helper_); } -// A remote peer owns the clipboard. This event is received in response to -// our request for TARGETS (GetAvailableMimeTypes), or a specific mime type -// (RequestClipboardData). -void X11ClipboardOzone::OnSelectionNotify( - const x11::SelectionNotifyEvent& event) { - // GetAvailableMimeTypes. - auto selection = static_cast(event.selection); - auto& selection_state = GetSelectionState(selection); - if (static_cast(event.target) == atom_targets_) { - std::vector targets; - GetArrayProperty(x_window_, x_property_, &targets); - - selection_state.mime_types.clear(); - for (auto target : targets) { - if (auto reply = connection_->GetAtomName({target}).Sync()) - selection_state.mime_types.push_back(std::move(reply->name)); - } - - // If we have a saved callback, invoke it now with expanded types, otherwise - // guess that we will want 'text/plain' and fetch it now. - if (selection_state.get_available_mime_types_callback) { - std::vector result(selection_state.mime_types); - ExpandTypes(&result); - std::move(selection_state.get_available_mime_types_callback) - .Run(std::move(result)); - } else { - selection_state.data_mime_type = kMimeTypeText; - ReadRemoteClipboard(selection); - } - } - - // RequestClipboardData. - if (static_cast(event.property) == x_property_) { - x11::Atom type; - std::vector data; - GetArrayProperty(x_window_, x_property_, &data, &type); - x11::DeleteProperty(x_window_, x_property_); - if (type != x11::Atom::None) - selection_state.data = scoped_refptr( - base::RefCountedBytes::TakeVector(&data)); - - // If we have a saved callback, invoke it now, otherwise this was a prefetch - // and we have already saved |data_| for the next call to - // |RequestClipboardData|. - if (selection_state.request_clipboard_data_callback) { - selection_state.request_data_map->emplace(selection_state.data_mime_type, - selection_state.data); - std::move(selection_state.request_clipboard_data_callback) - .Run(selection_state.data); - } - } else if (static_cast(event.property) == x11::Atom::None && - selection_state.request_clipboard_data_callback) { - // If the remote peer could not send data in the format we requested, - // or failed for any reason, we will send empty data. - std::move(selection_state.request_clipboard_data_callback) - .Run(selection_state.data); - } -} - -void X11ClipboardOzone::OnSetSelectionOwnerNotify( - const x11::XFixes::SelectionNotifyEvent& event) { - // Reset state and fetch remote clipboard if there is a new remote owner. - x11::Atom selection = event.selection; - if (!IsSelectionOwner(BufferForSelectionAtom(selection))) { - auto& selection_state = GetSelectionState(selection); - selection_state.mime_types.clear(); - selection_state.data_mime_type.clear(); - selection_state.data.reset(); - QueryTargets(selection); - } - - // Increase the sequence number if the callback is set. - if (update_sequence_cb_) - update_sequence_cb_.Run(BufferForSelectionAtom(selection)); -} - -x11::Atom X11ClipboardOzone::SelectionAtomForBuffer( - ClipboardBuffer buffer) const { - switch (buffer) { - case ClipboardBuffer::kCopyPaste: - return atom_clipboard_; - case ClipboardBuffer::kSelection: - return x11::Atom::PRIMARY; - default: - NOTREACHED(); - return x11::Atom::None; - } -} - -ClipboardBuffer X11ClipboardOzone::BufferForSelectionAtom( - x11::Atom selection) const { - if (selection == x11::Atom::PRIMARY) - return ClipboardBuffer::kSelection; - if (selection == atom_clipboard_) - return ClipboardBuffer::kCopyPaste; - NOTREACHED(); - return ClipboardBuffer::kCopyPaste; -} - -X11ClipboardOzone::SelectionState& X11ClipboardOzone::GetSelectionState( - x11::Atom selection) { - DCHECK(Contains(selection_state_, selection)); - return *selection_state_[selection]; -} - -void X11ClipboardOzone::QueryTargets(x11::Atom selection) { - GetSelectionState(selection).mime_types.clear(); - connection_->ConvertSelection({x_window_, selection, atom_targets_, - x_property_, x11::Time::CurrentTime}); -} - -void X11ClipboardOzone::ReadRemoteClipboard(x11::Atom selection) { - auto& selection_state = GetSelectionState(selection); - selection_state.data.reset(); - // Allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING. - std::string target = selection_state.data_mime_type; - if (!Contains(selection_state.mime_types, target)) { - if (target == kMimeTypeText) { - target = kMimeTypeLinuxString; - } else if (target == kMimeTypeTextUtf8) { - target = kMimeTypeLinuxUtf8String; - } - } - - connection_->ConvertSelection({x_window_, selection, x11::GetAtom(target), - x_property_, x11::Time::CurrentTime}); -} +X11ClipboardOzone::~X11ClipboardOzone() = default; void X11ClipboardOzone::OfferClipboardData( ClipboardBuffer buffer, const PlatformClipboard::DataMap& data_map, PlatformClipboard::OfferDataClosure callback) { - const x11::Atom selection = SelectionAtomForBuffer(buffer); - auto& selection_state = GetSelectionState(selection); - const auto timestamp = - static_cast(X11EventSource::GetInstance()->GetTimestamp()); - selection_state.acquired_selection_timestamp = timestamp; - selection_state.offer_data_map = data_map; - // Only take ownership if we are using xfixes. - // TODO(joelhockey): Make clipboard work without xfixes. - if (using_xfixes_) { - connection_->SetSelectionOwner({x_window_, selection, timestamp}); - } + DCHECK(!callback.is_null()); + helper_->CreateNewClipboardData(); + for (const auto& item : data_map) + helper_->InsertMapping(item.first, item.second); + helper_->TakeOwnershipOfSelection(buffer); std::move(callback).Run(); } void X11ClipboardOzone::RequestClipboardData( ClipboardBuffer buffer, const std::string& mime_type, - PlatformClipboard::DataMap* data_map, PlatformClipboard::RequestDataClosure callback) { - const x11::Atom selection = SelectionAtomForBuffer(buffer); - auto& selection_state = GetSelectionState(selection); - // If we are not using xfixes, return empty data. - // TODO(joelhockey): Make clipboard work without xfixes. - // If we have already prefetched the clipboard for the correct mime type, - // then send it right away, otherwise save the callback and attempt to get the - // requested mime type from the remote clipboard. - if (!using_xfixes_ || - (selection_state.data_mime_type == mime_type && selection_state.data && - !selection_state.data->data().empty())) { - data_map->emplace(mime_type, selection_state.data); - std::move(callback).Run(selection_state.data); - return; - } - - // If we know the available mime types, and it is not this, send empty now. - if (!selection_state.mime_types.empty() && - !Contains(selection_state.mime_types, mime_type)) { - std::move(callback).Run(PlatformClipboard::Data()); - return; - } - - selection_state.data_mime_type = mime_type; - selection_state.request_data_map = data_map; - DCHECK(selection_state.request_clipboard_data_callback.is_null()); - selection_state.request_clipboard_data_callback = std::move(callback); - ReadRemoteClipboard(selection); + DCHECK(!callback.is_null()); + auto atoms = + mime_type == kMimeTypeText + ? helper_->GetTextAtoms() + : helper_->GetAtomsForFormat(ClipboardFormatType::GetType(mime_type)); + auto selection_data = helper_->Read(buffer, atoms); + std::move(callback).Run(selection_data.TakeBytes()); } void X11ClipboardOzone::GetAvailableMimeTypes( ClipboardBuffer buffer, PlatformClipboard::GetMimeTypesClosure callback) { - const x11::Atom selection = SelectionAtomForBuffer(buffer); - auto& selection_state = GetSelectionState(selection); - // If we are not using xfixes, return empty data. - // TODO(joelhockey): Make clipboard work without xfixes. - // If we already have the list of supported mime types, send the expanded list - // of types right away, otherwise save the callback and get the list of - // TARGETS from the remote clipboard. - if (!using_xfixes_ || !selection_state.mime_types.empty()) { - std::vector result(selection_state.mime_types); - ExpandTypes(&result); - std::move(callback).Run(std::move(result)); - return; - } - DCHECK(selection_state.get_available_mime_types_callback.is_null()); - selection_state.get_available_mime_types_callback = std::move(callback); - QueryTargets(selection); + DCHECK(!callback.is_null()); + // This is the only function clients may use to request available formats, so + // include both standard and platform-specific (atom names) values. + // TODO(crbug.com/1165466): Consider adding a way of filtering mime types and + // querying availability of specific formats, so implementations can optimize + // it, if possible. E.g: Avoid multiple roundtrips to check if a given format + // is available. See ClipboardX11::IsFormatAvailable for example. + auto types = helper_->GetAvailableTypes(buffer); + auto atoms = helper_->GetAvailableAtomNames(buffer); + std::set uniq(types.begin(), types.end()); + uniq.insert(atoms.begin(), atoms.end()); + std::move(callback).Run({uniq.begin(), uniq.end()}); } bool X11ClipboardOzone::IsSelectionOwner(ClipboardBuffer buffer) { - // If we are not using xfixes, then we are always the owner. - // TODO(joelhockey): Make clipboard work without xfixes. - if (!using_xfixes_) - return true; - - auto reply = - connection_->GetSelectionOwner({SelectionAtomForBuffer(buffer)}).Sync(); - return reply && reply->owner == x_window_; + return helper_->IsSelectionOwner(buffer); } void X11ClipboardOzone::SetSequenceNumberUpdateCb( @@ -410,4 +78,9 @@ bool X11ClipboardOzone::IsSelectionBufferAvailable() const { return true; } +void X11ClipboardOzone::OnSelectionChanged(ClipboardBuffer buffer) { + if (update_sequence_cb_) + update_sequence_cb_.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 4802f02ee08..1c8986e275a 100644 --- a/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h +++ b/chromium/ui/ozone/platform/x11/x11_clipboard_ozone.h @@ -5,19 +5,17 @@ #ifndef UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_OZONE_H_ #define UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_OZONE_H_ +#include #include -#include #include "base/callback.h" -#include "base/containers/flat_map.h" -#include "ui/gfx/x/connection.h" -#include "ui/gfx/x/event.h" -#include "ui/gfx/x/xfixes.h" -#include "ui/gfx/x/xproto.h" +#include "ui/base/clipboard/clipboard_buffer.h" #include "ui/ozone/public/platform_clipboard.h" namespace ui { +class XClipboardHelper; + // Handles clipboard operations for X11. // Registers to receive standard X11 events, as well as // XFixesSetSelectionOwnerNotify. When the remote owner changes, TARGETS and @@ -26,9 +24,11 @@ namespace ui { // text/plain. Otherwise GetAvailableMimeTypes and RequestClipboardData call // the appropriate X11 functions and invoke callbacks when the associated events // are received. -class X11ClipboardOzone : public PlatformClipboard, public x11::EventObserver { +class X11ClipboardOzone : public PlatformClipboard { public: X11ClipboardOzone(); + X11ClipboardOzone(const X11ClipboardOzone&) = delete; + X11ClipboardOzone& operator=(const X11ClipboardOzone&) = delete; ~X11ClipboardOzone() override; // PlatformClipboard: @@ -39,7 +39,6 @@ class X11ClipboardOzone : public PlatformClipboard, public x11::EventObserver { void RequestClipboardData( ClipboardBuffer buffer, const std::string& mime_type, - PlatformClipboard::DataMap* data_map, PlatformClipboard::RequestDataClosure callback) override; void GetAvailableMimeTypes( ClipboardBuffer buffer, @@ -50,64 +49,12 @@ class X11ClipboardOzone : public PlatformClipboard, public x11::EventObserver { bool IsSelectionBufferAvailable() const override; private: - struct SelectionState; - - // x11::EventObserver: - void OnEvent(const x11::Event& xev) override; - - void OnSelectionRequest(const x11::SelectionRequestEvent& event); - void OnSelectionNotify(const x11::SelectionNotifyEvent& event); - void OnSetSelectionOwnerNotify( - const x11::XFixes::SelectionNotifyEvent& event); - - // Returns an X atom for a clipboard buffer type. - x11::Atom SelectionAtomForBuffer(ClipboardBuffer buffer) const; - - // Returns a clipboard buffer type for an X atom for a selection name of the - // system clipboard buffer. - ClipboardBuffer BufferForSelectionAtom(x11::Atom selection) const; - - // Returns the state for the given selection; - SelectionState& GetSelectionState(x11::Atom selection); - - // Queries the current clipboard owner for what mime types are available by - // sending XConvertSelection with target=TARGETS. After sending this, we - // will receive a SelectionNotify event with xselection.target=TARGETS which - // is processed in |OnSelectionNotify|. - void QueryTargets(x11::Atom selection); + void OnSelectionChanged(ClipboardBuffer buffer); - // Reads the contents of the remote clipboard by sending XConvertSelection - // with target=. After sending this, we will receive a - // SelectionNotify event with xselection.target= which is processed - // in |OnSelectionNotify|. - void ReadRemoteClipboard(x11::Atom selection); - - // Local cache of atoms. - const x11::Atom atom_clipboard_; - const x11::Atom atom_targets_; - const x11::Atom atom_timestamp_; - - // The property on |x_window_| which will receive remote clipboard contents. - const x11::Atom x_property_; - - // Our X11 state. - x11::Connection* connection_; - - // Input-only window used as a selection owner. - const x11::Window x_window_; - - // If XFixes is unavailable, this clipboard window will not register to - // receive events and no processing will take place. - // TODO(joelhockey): Make clipboard work without xfixes. - bool using_xfixes_ = false; + const std::unique_ptr helper_; // Notifies whenever clipboard sequence number is changed. PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_; - - // State of selections served by this instance. - base::flat_map> selection_state_; - - DISALLOW_COPY_AND_ASSIGN(X11ClipboardOzone); }; } // namespace ui diff --git a/chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.cc b/chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.cc new file mode 100644 index 00000000000..760dfc34060 --- /dev/null +++ b/chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.cc @@ -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. + +#include "ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h" + +namespace ui { + +X11GlobalShortcutListenerOzone::X11GlobalShortcutListenerOzone( + PlatformGlobalShortcutListenerDelegate* delegate) + : PlatformGlobalShortcutListener(delegate) {} + +X11GlobalShortcutListenerOzone::~X11GlobalShortcutListenerOzone() { + if (delegate()) + delegate()->OnPlatformListenerDestroyed(); +} + +void X11GlobalShortcutListenerOzone::StartListening() { + XGlobalShortcutListener::StartListening(); +} + +void X11GlobalShortcutListenerOzone::StopListening() { + XGlobalShortcutListener::StopListening(); +} + +bool X11GlobalShortcutListenerOzone::RegisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) { + return XGlobalShortcutListener::RegisterAccelerator( + key_code, is_alt_down, is_ctrl_down, is_shift_down); +} + +void X11GlobalShortcutListenerOzone::UnregisterAccelerator( + KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) { + return XGlobalShortcutListener::UnregisterAccelerator( + key_code, is_alt_down, is_ctrl_down, is_shift_down); +} + +void X11GlobalShortcutListenerOzone::OnKeyPressed(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) { + if (delegate()) { + delegate()->OnKeyPressed(key_code, is_alt_down, is_ctrl_down, + is_shift_down); + } +} + +} // namespace ui diff --git a/chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h b/chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h new file mode 100644 index 00000000000..0f1980abdca --- /dev/null +++ b/chromium/ui/ozone/platform/x11/x11_global_shortcut_listener_ozone.h @@ -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. + +#ifndef UI_OZONE_PLATFORM_X11_X11_GLOBAL_SHORTCUT_LISTENER_OZONE_H_ +#define UI_OZONE_PLATFORM_X11_X11_GLOBAL_SHORTCUT_LISTENER_OZONE_H_ + +#include "ui/base/x/x11_global_shortcut_listener.h" +#include "ui/ozone/public/platform_global_shortcut_listener.h" + +namespace ui { + +class X11GlobalShortcutListenerOzone : public PlatformGlobalShortcutListener, + public ui::XGlobalShortcutListener { + public: + explicit X11GlobalShortcutListenerOzone( + PlatformGlobalShortcutListenerDelegate* delegate); + X11GlobalShortcutListenerOzone(const X11GlobalShortcutListenerOzone&) = + delete; + X11GlobalShortcutListenerOzone& operator=( + const X11GlobalShortcutListenerOzone&) = delete; + ~X11GlobalShortcutListenerOzone() override; + + private: + // GlobalShortcutListener implementation. + void StartListening() override; + void StopListening() override; + bool RegisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) override; + void UnregisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) override; + + // ui::XGlobalShortcutListener: + void OnKeyPressed(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) override; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_X11_X11_GLOBAL_SHORTCUT_LISTENER_OZONE_H_ diff --git a/chromium/ui/ozone/platform/x11/x11_menu_utils.cc b/chromium/ui/ozone/platform/x11/x11_menu_utils.cc index 9633b73f308..c4121a9122f 100644 --- a/chromium/ui/ozone/platform/x11/x11_menu_utils.cc +++ b/chromium/ui/ozone/platform/x11/x11_menu_utils.cc @@ -21,7 +21,7 @@ int X11MenuUtils::GetCurrentKeyModifiers() const { std::string X11MenuUtils::ToDBusKeySym(KeyboardCode code) const { return base::UTF16ToUTF8( - base::string16(1, ui::GetUnicodeCharacterFromXKeySym( + std::u16string(1, ui::GetUnicodeCharacterFromXKeySym( XKeysymForWindowsKeyCode(code, false)))); } diff --git a/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.cc b/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.cc index 8aa26409a72..d5666478f95 100644 --- a/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.cc +++ b/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.cc @@ -53,6 +53,10 @@ void X11OzoneUIControlsTestHelper::RunClosureAfterAllPendingUIEvents( std::move(closure)); } +bool X11OzoneUIControlsTestHelper::MustUseUiControlsForMoveCursorTo() { + return false; +} + OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperX11() { return new X11OzoneUIControlsTestHelper(); } diff --git a/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.h b/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.h index 4026dc440d4..c5b0679e59c 100644 --- a/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.h +++ b/chromium/ui/ozone/platform/x11/x11_ozone_ui_controls_test_helper.h @@ -39,6 +39,7 @@ class X11OzoneUIControlsTestHelper : public OzoneUIControlsTestHelper { const gfx::Point& mouse_root_loc, base::OnceClosure closure) override; void RunClosureAfterAllPendingUIEvents(base::OnceClosure closure) override; + bool MustUseUiControlsForMoveCursorTo() override; private: X11UIControlsTestHelper x11_ui_controls_test_helper_; diff --git a/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc b/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc index 718cb627f4f..5e70823134f 100644 --- a/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc +++ b/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc @@ -4,6 +4,7 @@ #include "ui/ozone/platform/x11/x11_screen_ozone.h" +#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_util.h" @@ -21,20 +22,6 @@ namespace ui { -namespace { - -float GetDeviceScaleFactor() { - float device_scale_factor = 1.0f; - // TODO(crbug.com/891175): Implement PlatformScreen for X11 - // Get device scale factor using scale factor and resolution like - // 'GtkUi::GetRawDeviceScaleFactor'. - if (display::Display::HasForceDeviceScaleFactor()) - device_scale_factor = display::Display::GetForcedDeviceScaleFactor(); - return device_scale_factor; -} - -} // namespace - X11ScreenOzone::X11ScreenOzone() : window_manager_(X11WindowManager::GetInstance()), x11_display_manager_(std::make_unique(this)) { @@ -83,7 +70,7 @@ gfx::Point X11ScreenOzone::GetCursorScreenPoint() const { } // TODO(danakj): Should this be rounded? Or kept as a floating point? return gfx::ToFlooredPoint( - gfx::ConvertPointToDips(*point_in_pixels, GetDeviceScaleFactor())); + gfx::ConvertPointToDips(*point_in_pixels, GetXDisplayScaleFactor())); } gfx::AcceleratedWidget X11ScreenOzone::GetAcceleratedWidgetAtScreenPoint( @@ -111,7 +98,7 @@ display::Display X11ScreenOzone::GetDisplayNearestPoint( display::Display X11ScreenOzone::GetDisplayMatching( const gfx::Rect& match_rect_in_pixels) const { gfx::Rect match_rect = gfx::ToEnclosingRect( - gfx::ConvertRectToDips(match_rect_in_pixels, GetDeviceScaleFactor())); + gfx::ConvertRectToDips(match_rect_in_pixels, GetXDisplayScaleFactor())); const display::Display* matching_display = display::FindDisplayWithBiggestIntersection( x11_display_manager_->displays(), match_rect); @@ -146,8 +133,19 @@ std::string X11ScreenOzone::GetCurrentWorkspace() { base::Value X11ScreenOzone::GetGpuExtraInfoAsListValue( const gfx::GpuExtraInfo& gpu_extra_info) { - return ui::GpuExtraInfoAsListValue(gpu_extra_info.system_visual, - gpu_extra_info.rgba_visual); + auto result = GetDesktopEnvironmentInfoAsListValue(); + StoreGpuExtraInfoIntoListValue(gpu_extra_info.system_visual, + gpu_extra_info.rgba_visual, result); + StorePlatformNameIntoListValue(result, "x11"); + return result; +} + +void X11ScreenOzone::SetDeviceScaleFactor(float scale) { + if (device_scale_factor_ == scale) + return; + + device_scale_factor_ = scale; + x11_display_manager_->DispatchDelayedDisplayListUpdate(); } void X11ScreenOzone::OnEvent(const x11::Event& xev) { @@ -165,7 +163,9 @@ void X11ScreenOzone::OnXDisplayListUpdated() { } float X11ScreenOzone::GetXDisplayScaleFactor() const { - return GetDeviceScaleFactor(); + return display::Display::HasForceDeviceScaleFactor() + ? display::Display::GetForcedDeviceScaleFactor() + : device_scale_factor_; } } // namespace ui diff --git a/chromium/ui/ozone/platform/x11/x11_screen_ozone.h b/chromium/ui/ozone/platform/x11/x11_screen_ozone.h index 4f498468610..5b0ab16d472 100644 --- a/chromium/ui/ozone/platform/x11/x11_screen_ozone.h +++ b/chromium/ui/ozone/platform/x11/x11_screen_ozone.h @@ -54,6 +54,7 @@ class X11ScreenOzone : public PlatformScreen, std::string GetCurrentWorkspace() override; base::Value GetGpuExtraInfoAsListValue( const gfx::GpuExtraInfo& gpu_extra_info) override; + void SetDeviceScaleFactor(float scale) override; // Overridden from x11::EventObserver: void OnEvent(const x11::Event& event) override; @@ -70,6 +71,10 @@ class X11ScreenOzone : public PlatformScreen, X11WindowManager* const window_manager_; std::unique_ptr x11_display_manager_; + // Scale value that DesktopScreenOzoneLinux sets by listening to + // DeviceScaleFactorObserver. + float device_scale_factor_ = 1.0f; + DISALLOW_COPY_AND_ASSIGN(X11ScreenOzone); }; diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc index e081380d06f..698327d3489 100644 --- a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc +++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc @@ -34,8 +34,8 @@ class GLOzoneEGLX11 : public GLOzoneEGL { // GLOzone: bool InitializeStaticGLBindings( - gl::GLImplementation implementation) override { - is_swiftshader_ = (implementation == gl::kGLImplementationSwiftShaderGL); + const gl::GLImplementationParts& implementation) override { + is_swiftshader_ = gl::IsSoftwareGLImplementation(implementation); return GLOzoneEGL::InitializeStaticGLBindings(implementation); } @@ -45,16 +45,30 @@ class GLOzoneEGLX11 : public GLOzoneEGL { return gl::InitializeGLSurface( base::MakeRefCounted(window)); } else { - return gl::InitializeGLSurface( - base::MakeRefCounted( + switch (gl::GetGLImplementation()) { + case gl::kGLImplementationEGLGLES2: + DCHECK(window != gfx::kNullAcceleratedWidget); + return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11GLES2( + static_cast(window))); + case gl::kGLImplementationEGLANGLE: + DCHECK(window != gfx::kNullAcceleratedWidget); + return gl::InitializeGLSurface(new gl::NativeViewGLSurfaceEGLX11( static_cast(window))); + default: + NOTREACHED(); + return nullptr; + } } } scoped_refptr CreateOffscreenGLSurface( const gfx::Size& size) override { - return gl::InitializeGLSurface( - base::MakeRefCounted(size)); + if (gl::GLSurfaceEGL::IsEGLSurfacelessContextSupported() && + size.width() == 0 && size.height() == 0) { + return InitializeGLSurface(new gl::SurfacelessEGL(size)); + } else { + return InitializeGLSurface(new gl::PbufferGLSurfaceEGL(size)); + } } protected: @@ -64,7 +78,8 @@ class GLOzoneEGLX11 : public GLOzoneEGL { x11::Connection::Get()->GetXlibDisplay().display())); } - bool LoadGLES2Bindings(gl::GLImplementation implementation) override { + bool LoadGLES2Bindings( + const gl::GLImplementationParts& implementation) override { return LoadDefaultEGLGLES2Bindings(implementation); } @@ -86,16 +101,18 @@ X11SurfaceFactory::~X11SurfaceFactory() = default; std::vector X11SurfaceFactory::GetAllowedGLImplementations() { - return std::vector{gl::kGLImplementationDesktopGL, - gl::kGLImplementationEGLGLES2, - gl::kGLImplementationSwiftShaderGL}; + return std::vector{ + gl::kGLImplementationDesktopGL, gl::kGLImplementationEGLGLES2, + gl::kGLImplementationEGLANGLE, gl::kGLImplementationSwiftShaderGL}; } -GLOzone* X11SurfaceFactory::GetGLOzone(gl::GLImplementation implementation) { - switch (implementation) { +GLOzone* X11SurfaceFactory::GetGLOzone( + const gl::GLImplementationParts& implementation) { + switch (implementation.gl) { case gl::kGLImplementationDesktopGL: return glx_implementation_.get(); case gl::kGLImplementationEGLGLES2: + case gl::kGLImplementationEGLANGLE: case gl::kGLImplementationSwiftShaderGL: return egl_implementation_.get(); default: diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.h b/chromium/ui/ozone/platform/x11/x11_surface_factory.h index 70209cc94be..7600c923269 100644 --- a/chromium/ui/ozone/platform/x11/x11_surface_factory.h +++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.h @@ -25,7 +25,7 @@ class X11SurfaceFactory : public SurfaceFactoryOzone { // SurfaceFactoryOzone: std::vector GetAllowedGLImplementations() override; - GLOzone* GetGLOzone(gl::GLImplementation implementation) override; + GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override; #if BUILDFLAG(ENABLE_VULKAN) std::unique_ptr CreateVulkanImplementation( bool use_swiftshader, diff --git a/chromium/ui/ozone/platform/x11/x11_utils.cc b/chromium/ui/ozone/platform/x11/x11_utils.cc new file mode 100644 index 00000000000..47f25b31f41 --- /dev/null +++ b/chromium/ui/ozone/platform/x11/x11_utils.cc @@ -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. + +#include "ui/ozone/platform/x11/x11_utils.h" + +#include "ui/base/x/x11_util.h" + +namespace ui { + +X11Utils::X11Utils() = default; + +X11Utils::~X11Utils() = default; + +gfx::ImageSkia X11Utils::GetNativeWindowIcon(intptr_t target_window_id) { + return ui::GetNativeWindowIcon(target_window_id); +} + +} // namespace ui diff --git a/chromium/ui/ozone/platform/x11/x11_utils.h b/chromium/ui/ozone/platform/x11/x11_utils.h new file mode 100644 index 00000000000..0705dd0e89e --- /dev/null +++ b/chromium/ui/ozone/platform/x11/x11_utils.h @@ -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. + +#ifndef UI_OZONE_PLATFORM_X11_X11_UTILS_H_ +#define UI_OZONE_PLATFORM_X11_X11_UTILS_H_ + +#include "ui/ozone/public/platform_utils.h" + +namespace ui { + +class X11Utils : public PlatformUtils { + public: + X11Utils(); + X11Utils(const X11Utils&) = delete; + X11Utils& operator=(const X11Utils&) = delete; + ~X11Utils() override; + + gfx::ImageSkia GetNativeWindowIcon(intptr_t target_window_id) override; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_X11_X11_UTILS_H_ diff --git a/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc index 63037c7c771..4f4ec192809 100644 --- a/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc +++ b/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc @@ -258,7 +258,7 @@ TEST_F(X11WindowOzoneTest, ToggleFullscreen) { constexpr gfx::Rect bounds(30, 80, 800, 600); auto window = CreatePlatformWindow(&delegate, bounds, &widget); - EXPECT_CALL(delegate, OnBoundsChanged(screen_bounds_in_px)); + EXPECT_CALL(delegate, OnBoundsChanged(testing::Eq(screen_bounds_in_px))); window->ToggleFullscreen(); } diff --git a/chromium/ui/ozone/public/gl_ozone.h b/chromium/ui/ozone/public/gl_ozone.h index a12283fdd8c..08ff2789c44 100644 --- a/chromium/ui/ozone/public/gl_ozone.h +++ b/chromium/ui/ozone/public/gl_ozone.h @@ -35,7 +35,7 @@ class COMPONENT_EXPORT(OZONE_BASE) GLOzone { // Initializes static GL bindings and sets GL implementation. virtual bool InitializeStaticGLBindings( - gl::GLImplementation implementation) = 0; + const gl::GLImplementationParts& implementation) = 0; // Performs any one off initialization for GL implementation. virtual bool InitializeGLOneOffPlatform() = 0; diff --git a/chromium/ui/ozone/public/mojom/device_cursor.mojom b/chromium/ui/ozone/public/mojom/device_cursor.mojom index f165e5eb833..f938ea29f94 100644 --- a/chromium/ui/ozone/public/mojom/device_cursor.mojom +++ b/chromium/ui/ozone/public/mojom/device_cursor.mojom @@ -4,6 +4,7 @@ module ui.ozone.mojom; +import "mojo/public/mojom/base/time.mojom"; import "skia/public/mojom/bitmap.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; import "ui/gfx/mojom/accelerated_widget.mojom"; @@ -12,12 +13,11 @@ import "ui/gfx/mojom/accelerated_widget.mojom"; // where functionality equivalent to the DrmCursorProxy is exposed by a // dedicated thread within the Ozone platform. interface DeviceCursor { - // Sets the cursor |bitmaps| on |window| at |point| with - // |frame_delay_ms|. + // Sets the cursor |bitmaps| on |window| at |point| with |frame_delay|. SetCursor(gfx.mojom.AcceleratedWidget window, array bitmaps, gfx.mojom.Point point, - int32 frame_delay_ms); + mojo_base.mojom.TimeDelta frame_delay); // Moves the cursor in |window| to |point|. MoveCursor(gfx.mojom.AcceleratedWidget window, gfx.mojom.Point point); 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 1a99bc0bb98..bf5e10f9eb2 100644 --- a/chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom +++ b/chromium/ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom @@ -87,6 +87,8 @@ interface WaylandBufferManagerGpu { // instance to avoid using zwp_linux_dmabuf protocol by setting // |supports_dma_buf| to false, which results in using wl_egl_surface in a // single process mode, and software rendering in a multiple process mode. + // |supports_viewporter| indicates whether the Wayland server implements + // wp_viewporter extension to support cropping and scaling buffers. // |supports_acquire_fence| indicates whether acquire fences can be submitted // with buffers for wayland servers to wait on before accessing buffer // contents. @@ -94,6 +96,7 @@ interface WaylandBufferManagerGpu { map> buffer_formats_with_modifiers, bool supports_dma_buf, + bool supports_viewporter, bool supports_acquire_fence); // Signals about swap completion. diff --git a/chromium/ui/ozone/public/ozone_gpu_test_helper.cc b/chromium/ui/ozone/public/ozone_gpu_test_helper.cc index 1e5e9883c3e..ed4333ef180 100644 --- a/chromium/ui/ozone/public/ozone_gpu_test_helper.cc +++ b/chromium/ui/ozone/public/ozone_gpu_test_helper.cc @@ -5,6 +5,7 @@ #include "ui/ozone/public/ozone_gpu_test_helper.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/message_loop/message_pump_type.h" #include "base/run_loop.h" #include "base/threading/thread.h" diff --git a/chromium/ui/ozone/public/ozone_platform.cc b/chromium/ui/ozone/public/ozone_platform.cc index 29fd78fa4c7..98cfa91306c 100644 --- a/chromium/ui/ozone/public/ozone_platform.cc +++ b/chromium/ui/ozone/public/ozone_platform.cc @@ -13,6 +13,7 @@ #include "ui/events/devices/device_data_manager.h" #include "ui/ozone/platform_object.h" #include "ui/ozone/platform_selection.h" +#include "ui/ozone/public/platform_global_shortcut_listener.h" #include "ui/ozone/public/platform_menu_utils.h" #include "ui/ozone/public/platform_screen.h" #include "ui/ozone/public/platform_user_input_monitor.h" @@ -104,6 +105,16 @@ PlatformMenuUtils* OzonePlatform::GetPlatformMenuUtils() { return nullptr; } +PlatformUtils* OzonePlatform::GetPlatformUtils() { + return nullptr; +} + +PlatformGlobalShortcutListener* +OzonePlatform::GetPlatformGlobalShortcutListener( + PlatformGlobalShortcutListenerDelegate* delegate) { + return nullptr; +} + bool OzonePlatform::IsNativePixmapConfigSupported( gfx::BufferFormat format, gfx::BufferUsage usage) const { diff --git a/chromium/ui/ozone/public/ozone_platform.h b/chromium/ui/ozone/public/ozone_platform.h index 274915a23e7..886fc32c51e 100644 --- a/chromium/ui/ozone/public/ozone_platform.h +++ b/chromium/ui/ozone/public/ozone_platform.h @@ -31,9 +31,12 @@ class InputController; class OverlayManagerOzone; class PlatformClipboard; class PlatformGLEGLUtility; +class PlatformGlobalShortcutListener; +class PlatformGlobalShortcutListenerDelegate; class PlatformMenuUtils; class PlatformScreen; class PlatformUserInputMonitor; +class PlatformUtils; class SurfaceFactoryOzone; class SystemInputInjector; @@ -131,6 +134,10 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform { // be stacked below an AcceleratedWidget to make a widget opaque. bool needs_background_image = false; + // Wayland only: determines whether windows which are not top level ones + // should be given parents explicitly. + bool set_parent_for_non_top_level_windows = false; + // If true, the platform shows and updates the drag image. bool platform_shows_drag_image = true; @@ -216,6 +223,9 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform { gfx::AcceleratedWidget widget) = 0; virtual PlatformGLEGLUtility* GetPlatformGLEGLUtility(); virtual PlatformMenuUtils* GetPlatformMenuUtils(); + virtual PlatformUtils* GetPlatformUtils(); + virtual PlatformGlobalShortcutListener* GetPlatformGlobalShortcutListener( + PlatformGlobalShortcutListenerDelegate* delegate); // Returns true if the specified buffer format is supported. virtual bool IsNativePixmapConfigSupported(gfx::BufferFormat format, diff --git a/chromium/ui/ozone/public/ozone_ui_controls_test_helper.h b/chromium/ui/ozone/public/ozone_ui_controls_test_helper.h index 49beed55c42..a0bdd18f33e 100644 --- a/chromium/ui/ozone/public/ozone_ui_controls_test_helper.h +++ b/chromium/ui/ozone/public/ozone_ui_controls_test_helper.h @@ -52,6 +52,11 @@ class OzoneUIControlsTestHelper { // Executes closure after all pending ui events are sent. virtual void RunClosureAfterAllPendingUIEvents(base::OnceClosure closure) = 0; + + // Tells the client of OzoneUIControlsTestHelper that it must use + // SendMouseMotionNotifyEvent instead of calling MoveCursorTo via + // aura::Window. + virtual bool MustUseUiControlsForMoveCursorTo() = 0; }; COMPONENT_EXPORT(OZONE) diff --git a/chromium/ui/ozone/public/platform_clipboard.h b/chromium/ui/ozone/public/platform_clipboard.h index 941e2377307..e12ce50c592 100644 --- a/chromium/ui/ozone/public/platform_clipboard.h +++ b/chromium/ui/ozone/public/platform_clipboard.h @@ -58,16 +58,12 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformClipboard { const DataMap& data_map, OfferDataClosure callback) = 0; - // Reads data from host system clipboard given mime type. The data is - // stored in 'data_map'. - // - // RequestDataClosure is invoked to acknowledge that the requested clipboard - // data has been read and stored into 'data_map'. - using RequestDataClosure = - base::OnceCallback&)>; + // Reads data from host system clipboard given mime type. The resulting data + // is returned asynchronously through |callback|, whereas nullptr is returned + // if the request fails for some reason (i.e: no data available, etc). + using RequestDataClosure = base::OnceCallback; virtual void RequestClipboardData(ClipboardBuffer buffer, const std::string& mime_type, - DataMap* data_map, RequestDataClosure callback) = 0; // Gets the mime types of the data available for clipboard operations diff --git a/chromium/ui/ozone/public/platform_global_shortcut_listener.cc b/chromium/ui/ozone/public/platform_global_shortcut_listener.cc new file mode 100644 index 00000000000..cf75ab0659b --- /dev/null +++ b/chromium/ui/ozone/public/platform_global_shortcut_listener.cc @@ -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. + +#include "ui/ozone/public/platform_global_shortcut_listener.h" + +#include "base/check.h" + +namespace ui { + +PlatformGlobalShortcutListenerDelegate:: + ~PlatformGlobalShortcutListenerDelegate() = default; + +PlatformGlobalShortcutListener::PlatformGlobalShortcutListener( + PlatformGlobalShortcutListenerDelegate* delegate) + : delegate_(delegate) { + DCHECK(delegate_); +} + +PlatformGlobalShortcutListener::~PlatformGlobalShortcutListener() = default; + +} // namespace ui diff --git a/chromium/ui/ozone/public/platform_global_shortcut_listener.h b/chromium/ui/ozone/public/platform_global_shortcut_listener.h new file mode 100644 index 00000000000..a5b539d4e74 --- /dev/null +++ b/chromium/ui/ozone/public/platform_global_shortcut_listener.h @@ -0,0 +1,69 @@ +// 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_GLOBAL_SHORTCUT_LISTENER_H_ +#define UI_OZONE_PUBLIC_PLATFORM_GLOBAL_SHORTCUT_LISTENER_H_ + +#include "base/component_export.h" +#include "ui/events/keycodes/keyboard_codes.h" + +namespace ui { + +// The platform implementation should notify the wrapper through this +// interface when the registered shortcut is activated, or when the +// implementation is destroyed. +class COMPONENT_EXPORT(OZONE_BASE) PlatformGlobalShortcutListenerDelegate { + public: + // Called back when the previously registered key combination is pressed. + virtual void OnKeyPressed(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) = 0; + // Called back when the platform implementation is destroyed. + virtual void OnPlatformListenerDestroyed() = 0; + + protected: + virtual ~PlatformGlobalShortcutListenerDelegate(); +}; + +// The interface to Ozone platform's functionality exposed to Chrome via +// extensions::GlobalShortcutListenerOzone. +// +// Lifetimes of extensions::GlobalShortcutListenerOzone and the platform +// implementation are independent, so these entities should decouple +// explicitly upon destruction through OnPlatformListenerDestroyed() and +// ResetDelegate(), depending on which object is destroyed first. +class COMPONENT_EXPORT(OZONE_BASE) PlatformGlobalShortcutListener { + public: + explicit PlatformGlobalShortcutListener( + PlatformGlobalShortcutListenerDelegate* delegate); + virtual ~PlatformGlobalShortcutListener(); + + void ResetDelegate() { delegate_ = nullptr; } + + // The following interface serves the same purpose like the one defined in + // extensions::GlobalShortcutListener, and does it the same way. The only + // difference is that the platform can not use ui::Accelerator directly so it + // accepts it split into key code and modifiers. + virtual void StartListening() = 0; + virtual void StopListening() = 0; + virtual bool RegisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) = 0; + virtual void UnregisterAccelerator(KeyboardCode key_code, + bool is_alt_down, + bool is_ctrl_down, + bool is_shift_down) = 0; + + protected: + PlatformGlobalShortcutListenerDelegate* delegate() { return delegate_; } + + private: + PlatformGlobalShortcutListenerDelegate* delegate_; +}; + +} // namespace ui + +#endif // UI_OZONE_PUBLIC_PLATFORM_GLOBAL_SHORTCUT_LISTENER_H_ diff --git a/chromium/ui/ozone/public/platform_screen.cc b/chromium/ui/ozone/public/platform_screen.cc index 6700247c2d0..aef973d8f4f 100644 --- a/chromium/ui/ozone/public/platform_screen.cc +++ b/chromium/ui/ozone/public/platform_screen.cc @@ -43,4 +43,15 @@ base::Value PlatformScreen::GetGpuExtraInfoAsListValue( return base::Value(base::Value::Type::LIST); } +void PlatformScreen::SetDeviceScaleFactor(float scale) {} + +void PlatformScreen::StorePlatformNameIntoListValue( + base::Value& list_value, + const std::string& platform_name) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("description", base::Value("Ozone platform")); + dict.SetKey("value", base::Value(platform_name)); + list_value.Append(std::move(dict)); +} + } // namespace ui diff --git a/chromium/ui/ozone/public/platform_screen.h b/chromium/ui/ozone/public/platform_screen.h index aeb0572e5a7..91a9b587fe7 100644 --- a/chromium/ui/ozone/public/platform_screen.h +++ b/chromium/ui/ozone/public/platform_screen.h @@ -105,6 +105,14 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformScreen { virtual base::Value GetGpuExtraInfoAsListValue( const gfx::GpuExtraInfo& gpu_extra_info); + // Sets device scale factor received from external sources such as toolkits. + // Currently only used by Linux. + virtual void SetDeviceScaleFactor(float scale); + + protected: + void StorePlatformNameIntoListValue(base::Value& list_value, + const std::string& platform_name); + private: DISALLOW_COPY_AND_ASSIGN(PlatformScreen); }; diff --git a/chromium/ui/ozone/public/platform_utils.h b/chromium/ui/ozone/public/platform_utils.h new file mode 100644 index 00000000000..f89eda27d45 --- /dev/null +++ b/chromium/ui/ozone/public/platform_utils.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_PUBLIC_PLATFORM_UTILS_H_ +#define UI_OZONE_PUBLIC_PLATFORM_UTILS_H_ + +#include + +#include "base/component_export.h" + +namespace gfx { +class ImageSkia; +} + +namespace ui { + +// Platform-specific general util functions that didn't find their way to any +// other existing utilities, but they are required to be accessed outside +// Ozone. +class COMPONENT_EXPORT(OZONE_BASE) PlatformUtils { + public: + virtual ~PlatformUtils() = default; + + // Returns an icon for a native window referred by |target_window_id|. Can be + // any window on screen. + virtual gfx::ImageSkia GetNativeWindowIcon(intptr_t target_window_id) = 0; +}; + +} // namespace ui + +#endif // UI_OZONE_PUBLIC_PLATFORM_UTILS_H_ diff --git a/chromium/ui/ozone/public/surface_factory_ozone.cc b/chromium/ui/ozone/public/surface_factory_ozone.cc index c42cea806b1..45b415c7233 100644 --- a/chromium/ui/ozone/public/surface_factory_ozone.cc +++ b/chromium/ui/ozone/public/surface_factory_ozone.cc @@ -29,7 +29,8 @@ SurfaceFactoryOzone::GetAllowedGLImplementations() { return std::vector(); } -GLOzone* SurfaceFactoryOzone::GetGLOzone(gl::GLImplementation implementation) { +GLOzone* SurfaceFactoryOzone::GetGLOzone( + const gl::GLImplementationParts& implementation) { return nullptr; } diff --git a/chromium/ui/ozone/public/surface_factory_ozone.h b/chromium/ui/ozone/public/surface_factory_ozone.h index c68f421852a..729c91f8d96 100644 --- a/chromium/ui/ozone/public/surface_factory_ozone.h +++ b/chromium/ui/ozone/public/surface_factory_ozone.h @@ -73,7 +73,7 @@ class COMPONENT_EXPORT(OZONE_BASE) SurfaceFactoryOzone { // Returns the GLOzone to use for the specified GL implementation, or null if // GL implementation doesn't exist. - virtual GLOzone* GetGLOzone(gl::GLImplementation implementation); + virtual GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation); #if BUILDFLAG(ENABLE_VULKAN) // Creates the vulkan implementation. This object should be capable of diff --git a/chromium/ui/ozone/test/mock_platform_window_delegate.cc b/chromium/ui/ozone/test/mock_platform_window_delegate.cc index ceab1932f5b..76bdda12d91 100644 --- a/chromium/ui/ozone/test/mock_platform_window_delegate.cc +++ b/chromium/ui/ozone/test/mock_platform_window_delegate.cc @@ -10,4 +10,9 @@ MockPlatformWindowDelegate::MockPlatformWindowDelegate() {} MockPlatformWindowDelegate::~MockPlatformWindowDelegate() {} +bool operator==(const PlatformWindowDelegate::BoundsChange& bounds, + const gfx::Rect& rect) { + return bounds.bounds == rect; +} + } // namespace ui diff --git a/chromium/ui/ozone/test/mock_platform_window_delegate.h b/chromium/ui/ozone/test/mock_platform_window_delegate.h index f63d932acfc..bfeb9e67839 100644 --- a/chromium/ui/ozone/test/mock_platform_window_delegate.h +++ b/chromium/ui/ozone/test/mock_platform_window_delegate.h @@ -17,7 +17,7 @@ class MockPlatformWindowDelegate : public PlatformWindowDelegate { MockPlatformWindowDelegate(); ~MockPlatformWindowDelegate(); - MOCK_METHOD1(OnBoundsChanged, void(const gfx::Rect& new_bounds)); + MOCK_METHOD1(OnBoundsChanged, void(const BoundsChange& change)); MOCK_METHOD1(OnDamageRect, void(const gfx::Rect& damaged_region)); MOCK_METHOD1(DispatchEvent, void(Event* event)); MOCK_METHOD0(OnCloseRequest, void()); @@ -37,6 +37,9 @@ class MockPlatformWindowDelegate : public PlatformWindowDelegate { DISALLOW_COPY_AND_ASSIGN(MockPlatformWindowDelegate); }; +bool operator==(const PlatformWindowDelegate::BoundsChange& bounds, + const gfx::Rect& rect); + } // namespace ui #endif // UI_OZONE_TEST_MOCK_PLATFORM_WINDOW_DELEGATE_H_ diff --git a/chromium/ui/platform_window/common/platform_window_defaults.h b/chromium/ui/platform_window/common/platform_window_defaults.h index 1fdf907e325..dc572c446db 100644 --- a/chromium/ui/platform_window/common/platform_window_defaults.h +++ b/chromium/ui/platform_window/common/platform_window_defaults.h @@ -17,13 +17,15 @@ COMPONENT_EXPORT(PLATFORM_WINDOW_COMMON) bool UseTestConfigForPlatformWindows(); namespace test { // Sets that PlatformWindow should use test configuration. This can safely be -// called on all platforms but only has an effect for X11. +// called on all platforms but only has an effect for X11 and Wayland. // For X11 this sets the value of the |override_redirect| attribute used when // creating an X11 window to true. It is necessary to set this flag on for // various tests, otherwise the call to Show() blocks because it never receives // the MapNotify event. It is unclear why this is necessary, but might be // related to calls to XInitThreads(). +// +// For Wayland, forces visual size updates on every configuration event. COMPONENT_EXPORT(PLATFORM_WINDOW_COMMON) void EnableTestConfigForPlatformWindows(); diff --git a/chromium/ui/platform_window/platform_window.h b/chromium/ui/platform_window/platform_window.h index 58262d37d59..c88f3b9f19c 100644 --- a/chromium/ui/platform_window/platform_window.h +++ b/chromium/ui/platform_window/platform_window.h @@ -9,9 +9,7 @@ #include #include "base/component_export.h" -#include "base/strings/string16.h" #include "ui/base/class_property.h" -#include "ui/base/cursor/cursor.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/native_widget_types.h" #include "ui/platform_window/platform_window_delegate.h" @@ -25,6 +23,7 @@ class Transform; } // namespace gfx namespace ui { +using PlatformCursor = void*; // Generic PlatformWindow interface. class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow @@ -52,7 +51,7 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow virtual void SetBounds(const gfx::Rect& bounds) = 0; virtual gfx::Rect GetBounds() const = 0; - virtual void SetTitle(const base::string16& title) = 0; + virtual void SetTitle(const std::u16string& title) = 0; virtual void SetCapture() = 0; virtual void ReleaseCapture() = 0; diff --git a/chromium/ui/platform_window/platform_window_delegate.cc b/chromium/ui/platform_window/platform_window_delegate.cc index 8947a82bf78..e6a1a477c20 100644 --- a/chromium/ui/platform_window/platform_window_delegate.cc +++ b/chromium/ui/platform_window/platform_window_delegate.cc @@ -9,6 +9,13 @@ namespace ui { +PlatformWindowDelegate::BoundsChange::BoundsChange() = default; + +PlatformWindowDelegate::BoundsChange::BoundsChange(const gfx::Rect& bounds) + : bounds(bounds) {} + +PlatformWindowDelegate::BoundsChange::~BoundsChange() = default; + PlatformWindowDelegate::PlatformWindowDelegate() = default; PlatformWindowDelegate::~PlatformWindowDelegate() = default; @@ -25,4 +32,6 @@ SkPath PlatformWindowDelegate::GetWindowMaskForWindowShapeInPixels() { return SkPath(); } +void PlatformWindowDelegate::OnSurfaceFrameLockingChanged(bool lock) {} + } // namespace ui diff --git a/chromium/ui/platform_window/platform_window_delegate.h b/chromium/ui/platform_window/platform_window_delegate.h index 0de1b436dcf..6faa3bb304f 100644 --- a/chromium/ui/platform_window/platform_window_delegate.h +++ b/chromium/ui/platform_window/platform_window_delegate.h @@ -7,8 +7,14 @@ #include "base/component_export.h" #include "base/optional.h" +#include "build/build_config.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" +#if defined(OS_FUCHSIA) +#include "ui/gfx/geometry/insets.h" +#endif // defined(OS_FUCHSIA) + namespace gfx { class Rect; class Size; @@ -30,11 +36,36 @@ enum class PlatformWindowState { class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegate { public: + struct COMPONENT_EXPORT(PLATFORM_WINDOW) BoundsChange { + BoundsChange(); + BoundsChange(const gfx::Rect& bounds); + ~BoundsChange(); + + // The dimensions of the window, in physical window coordinates. + gfx::Rect bounds; + +#if defined(OS_FUCHSIA) + // The widths of border regions which are obscured by overlapping + // platform UI elements like onscreen keyboards. + // + // As an example, the overlap from an onscreen keyboard covering + // the bottom of the Window would be represented like this: + // + // +------------------------+ --- + // | | | + // | content | | + // | | | window + // +------------------------+ --- | + // | onscreen keyboard | | overlap | + // +------------------------+ --- --- + gfx::Insets system_ui_overlap; +#endif // defined(OS_FUCHSIA) + }; + PlatformWindowDelegate(); virtual ~PlatformWindowDelegate(); - // Note that |new_bounds| is in physical screen coordinates. - virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0; + virtual void OnBoundsChanged(const BoundsChange& change) = 0; // Note that |damaged_region| is in the platform-window's coordinates, in // physical pixels. @@ -70,6 +101,13 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegate { // This is used to create the non-rectangular window shape. virtual SkPath GetWindowMaskForWindowShapeInPixels(); + // Called while dragging maximized window when SurfaceFrame associated with + // this window is locked to normal state or unlocked from previously locked + // state. This function is used by chromeos for syncing + // `chromeos::kFrameRestoreLookKey` window property + // with lacros-chrome. + virtual void OnSurfaceFrameLockingChanged(bool lock); + // Called when the location of mouse pointer entered the window. This is // different from ui::ET_MOUSE_ENTERED which may not be generated when mouse // is captured either by implicitly or explicitly. diff --git a/chromium/ui/platform_window/stub/stub_window.cc b/chromium/ui/platform_window/stub/stub_window.cc index a111485f809..e3ba798dc80 100644 --- a/chromium/ui/platform_window/stub/stub_window.cc +++ b/chromium/ui/platform_window/stub/stub_window.cc @@ -4,7 +4,7 @@ #include "ui/platform_window/stub/stub_window.h" -#include "base/logging.h" +#include "base/notreached.h" #include "ui/platform_window/platform_window_delegate.h" namespace ui { @@ -47,7 +47,7 @@ gfx::Rect StubWindow::GetBounds() const { return bounds_; } -void StubWindow::SetTitle(const base::string16& title) {} +void StubWindow::SetTitle(const std::u16string& title) {} void StubWindow::SetCapture() {} diff --git a/chromium/ui/platform_window/stub/stub_window.h b/chromium/ui/platform_window/stub/stub_window.h index 7d2e7483f26..4c8ffecd9c2 100644 --- a/chromium/ui/platform_window/stub/stub_window.h +++ b/chromium/ui/platform_window/stub/stub_window.h @@ -35,7 +35,7 @@ class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow { void PrepareForShutdown() override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() const override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void SetCapture() override; void ReleaseCapture() override; void ToggleFullscreen() override; diff --git a/chromium/ui/platform_window/win/win_window.cc b/chromium/ui/platform_window/win/win_window.cc index cf00aaeb770..36b14c4edc3 100644 --- a/chromium/ui/platform_window/win/win_window.cc +++ b/chromium/ui/platform_window/win/win_window.cc @@ -6,8 +6,9 @@ #include #include +#include -#include "base/strings/string16.h" +#include "base/notreached.h" #include "base/strings/string_util_win.h" #include "ui/base/cursor/win/win_cursor.h" #include "ui/base/win/shell.h" @@ -101,7 +102,7 @@ gfx::Rect WinWindow::GetBounds() const { return gfx::Rect(cr); } -void WinWindow::SetTitle(const base::string16& title) { +void WinWindow::SetTitle(const std::u16string& title) { SetWindowText(hwnd(), base::as_wcstr(title)); } diff --git a/chromium/ui/platform_window/win/win_window.h b/chromium/ui/platform_window/win/win_window.h index 7bc9b3cdf87..00d61bd9c3a 100644 --- a/chromium/ui/platform_window/win/win_window.h +++ b/chromium/ui/platform_window/win/win_window.h @@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "ui/gfx/win/msg_util.h" #include "ui/gfx/win/window_impl.h" #include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_delegate.h" @@ -34,7 +35,7 @@ class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow, void PrepareForShutdown() override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() const override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void SetCapture() override; void ReleaseCapture() override; bool HasCapture() const override; diff --git a/chromium/ui/platform_window/wm/BUILD.gn b/chromium/ui/platform_window/wm/BUILD.gn index 96937273558..7f060579821 100644 --- a/chromium/ui/platform_window/wm/BUILD.gn +++ b/chromium/ui/platform_window/wm/BUILD.gn @@ -18,6 +18,7 @@ component("wm") { defines = [ "IS_WM_IMPL" ] + public_deps = [ "//ui/base/dragdrop:types" ] deps = [ "//ui/base", "//ui/platform_window", diff --git a/chromium/ui/platform_window/x11/BUILD.gn b/chromium/ui/platform_window/x11/BUILD.gn index 5b47c902e7d..dc65dc7a733 100644 --- a/chromium/ui/platform_window/x11/BUILD.gn +++ b/chromium/ui/platform_window/x11/BUILD.gn @@ -14,8 +14,12 @@ component("x11") { deps = [ "//base", "//build:chromeos_buildflags", + "//net", "//skia", "//ui/base", + "//ui/base:hit_test", + "//ui/base:wm_role_names", + "//ui/base/dragdrop:types", "//ui/base/x", "//ui/events", "//ui/events/devices", diff --git a/chromium/ui/platform_window/x11/DEPS b/chromium/ui/platform_window/x11/DEPS index f9f62a1b101..c9f97e2a705 100644 --- a/chromium/ui/platform_window/x11/DEPS +++ b/chromium/ui/platform_window/x11/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+net/base/network_interfaces.h", "+third_party/skia/include", "+ui/base", "+ui/events", diff --git a/chromium/ui/platform_window/x11/x11_window.cc b/chromium/ui/platform_window/x11/x11_window.cc index 967dd5f1c09..37649f7f332 100644 --- a/chromium/ui/platform_window/x11/x11_window.cc +++ b/chromium/ui/platform_window/x11/x11_window.cc @@ -5,13 +5,20 @@ #include "ui/platform_window/x11/x11_window.h" #include "base/strings/string_number_conversions.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "build/chromeos_buildflags.h" +#include "net/base/network_interfaces.h" +#include "third_party/skia/include/core/SkRegion.h" #include "ui/base/buildflags.h" +#include "ui/base/cursor/cursor.h" +#include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/base/hit_test_x11.h" #include "ui/base/ui_base_features.h" +#include "ui/base/wm_role_names_linux.h" #include "ui/base/x/x11_cursor.h" -#include "ui/base/x/x11_desktop_window_move_client.h" +#include "ui/base/x/x11_menu_registrar.h" #include "ui/base/x/x11_os_exchange_data_provider.h" #include "ui/base/x/x11_pointer_grab.h" #include "ui/base/x/x11_topmost_window_finder.h" @@ -23,8 +30,14 @@ #include "ui/events/ozone/events_ozone.h" #include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/x11/x11_event_source.h" +#include "ui/events/x/events_x_utils.h" #include "ui/events/x/x11_event_translation.h" +#include "ui/gfx/skia_util.h" +#include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/x11_path.h" #include "ui/gfx/x/x11_window_event_manager.h" +#include "ui/gfx/x/xproto.h" +#include "ui/gfx/x/xproto_util.h" #include "ui/platform_window/common/platform_window_defaults.h" #include "ui/platform_window/extensions/workspace_extension_delegate.h" #include "ui/platform_window/extensions/x11_extension_delegate.h" @@ -43,61 +56,6 @@ namespace { // Opacity for drag widget windows. constexpr float kDragWidgetOpacity = .75f; -XWindow::WindowOpacity GetXWindowOpacity(PlatformWindowOpacity opacity) { - using WindowOpacity = XWindow::WindowOpacity; - switch (opacity) { - case PlatformWindowOpacity::kInferOpacity: - return WindowOpacity::kInferOpacity; - case PlatformWindowOpacity::kOpaqueWindow: - return WindowOpacity::kOpaqueWindow; - case PlatformWindowOpacity::kTranslucentWindow: - return WindowOpacity::kTranslucentWindow; - } - NOTREACHED() << "Uknown window opacity."; - return WindowOpacity::kInferOpacity; -} - -XWindow::WindowType GetXWindowType(PlatformWindowType window_type) { - using WindowType = XWindow::WindowType; - switch (window_type) { - case PlatformWindowType::kWindow: - return WindowType::kWindow; - case PlatformWindowType::kMenu: - return WindowType::kMenu; - case PlatformWindowType::kTooltip: - return WindowType::kTooltip; - case PlatformWindowType::kPopup: - return WindowType::kPopup; - case PlatformWindowType::kDrag: - return WindowType::kDrag; - case PlatformWindowType::kBubble: - return WindowType::kBubble; - } - NOTREACHED() << "Uknown window type."; - return WindowType::kWindow; -} - -ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig( - const PlatformWindowInitProperties& properties) { - ui::XWindow::Configuration config; - config.type = GetXWindowType(properties.type); - config.opacity = GetXWindowOpacity(properties.opacity); - config.bounds = properties.bounds; - config.icon = properties.icon; - config.force_show_in_taskbar = properties.force_show_in_taskbar; - config.keep_on_top = properties.keep_on_top; - config.visible_on_all_workspaces = properties.visible_on_all_workspaces; - config.remove_standard_frame = properties.remove_standard_frame; - config.workspace = properties.workspace; - config.wm_class_name = properties.wm_class_name; - config.wm_class_class = properties.wm_class_class; - config.wm_role_name = properties.wm_role_name; - config.activatable = properties.activatable; - config.prefer_dark_theme = properties.prefer_dark_theme; - config.background_color = properties.background_color; - return config; -} - // Coalesce touch/mouse events if needed bool CoalesceEventsIfNeeded(const x11::Event& xev, EventType type, @@ -117,10 +75,118 @@ int GetKeyModifiers(const XDragDropClient* client) { return client->current_modifier_state(); } +// Special value of the _NET_WM_DESKTOP property which indicates that the window +// should appear on all workspaces/desktops. +const int32_t kAllWorkspaces = -1; + +constexpr char kX11WindowRolePopup[] = "popup"; +constexpr char kX11WindowRoleBubble[] = "bubble"; +constexpr char kDarkGtkThemeVariant[] = "dark"; + +constexpr long kSystemTrayRequestDock = 0; + +constexpr int kXembedInfoProtocolVersion = 0; +constexpr int kXembedFlagMap = 1 << 0; +constexpr int kXembedInfoFlags = kXembedFlagMap; + +enum CrossingFlags : uint8_t { + CROSSING_FLAG_FOCUS = 1 << 0, + CROSSING_FLAG_SAME_SCREEN = 1 << 1, +}; + +// In some situations, views tries to make a zero sized window, and that +// makes us crash. Make sure we have valid sizes. +gfx::Rect SanitizeBounds(const gfx::Rect& bounds) { + gfx::Size sanitized_size(std::max(bounds.width(), 1), + std::max(bounds.height(), 1)); + gfx::Rect sanitized_bounds(bounds.origin(), sanitized_size); + return sanitized_bounds; +} + +void SerializeImageRepresentation(const gfx::ImageSkiaRep& rep, + std::vector* data) { + uint32_t width = rep.GetWidth(); + data->push_back(width); + + uint32_t height = rep.GetHeight(); + data->push_back(height); + + const SkBitmap& bitmap = rep.GetBitmap(); + + for (uint32_t y = 0; y < height; ++y) + for (uint32_t x = 0; x < width; ++x) + data->push_back(bitmap.getColor(x, y)); +} + +x11::NotifyMode XI2ModeToXMode(x11::Input::NotifyMode xi2_mode) { + switch (xi2_mode) { + case x11::Input::NotifyMode::Normal: + return x11::NotifyMode::Normal; + case x11::Input::NotifyMode::Grab: + case x11::Input::NotifyMode::PassiveGrab: + return x11::NotifyMode::Grab; + case x11::Input::NotifyMode::Ungrab: + case x11::Input::NotifyMode::PassiveUngrab: + return x11::NotifyMode::Ungrab; + case x11::Input::NotifyMode::WhileGrabbed: + return x11::NotifyMode::WhileGrabbed; + default: + NOTREACHED(); + return x11::NotifyMode::Normal; + } +} + +x11::NotifyDetail XI2DetailToXDetail(x11::Input::NotifyDetail xi2_detail) { + switch (xi2_detail) { + case x11::Input::NotifyDetail::Ancestor: + return x11::NotifyDetail::Ancestor; + case x11::Input::NotifyDetail::Virtual: + return x11::NotifyDetail::Virtual; + case x11::Input::NotifyDetail::Inferior: + return x11::NotifyDetail::Inferior; + case x11::Input::NotifyDetail::Nonlinear: + return x11::NotifyDetail::Nonlinear; + case x11::Input::NotifyDetail::NonlinearVirtual: + return x11::NotifyDetail::NonlinearVirtual; + case x11::Input::NotifyDetail::Pointer: + return x11::NotifyDetail::Pointer; + case x11::Input::NotifyDetail::PointerRoot: + return x11::NotifyDetail::PointerRoot; + case x11::Input::NotifyDetail::None: + return x11::NotifyDetail::None; + } +} + +void SyncSetCounter(x11::Connection* connection, + x11::Sync::Counter counter, + int64_t value) { + x11::Sync::Int64 sync_value{.hi = value >> 32, .lo = value & 0xFFFFFFFF}; + connection->sync().SetCounter({counter, sync_value}); +} + +// Returns the whole path from |window| to the root. +std::vector GetParentsList(x11::Connection* connection, + x11::Window window) { + std::vector result; + while (window != x11::Window::None) { + result.push_back(window); + if (auto reply = connection->QueryTree({window}).Sync()) + window = reply->parent; + else + break; + } + return result; +} + } // namespace X11Window::X11Window(PlatformWindowDelegate* platform_window_delegate) - : platform_window_delegate_(platform_window_delegate) { + : platform_window_delegate_(platform_window_delegate), + connection_(x11::Connection::Get()), + x_root_window_(GetX11RootWindow()) { + DCHECK(connection_); + DCHECK_NE(x_root_window_, x11::Window::None); + // Set a class property key, which allows |this| to be used for interactive // events, e.g. move or resize. SetWmMoveResizeHandler(this, static_cast(this)); @@ -137,28 +203,201 @@ X11Window::~X11Window() { } void X11Window::Initialize(PlatformWindowInitProperties properties) { - XWindow::Configuration config = - ConvertInitPropertiesToXWindowConfig(properties); + PlatformWindowOpacity opacity = properties.opacity; + CreateXWindow(properties, opacity); + + // 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 + // ourselves. + if (properties.wm_role_name == kStatusIconWmRoleName && + !InitializeAsStatusIcon()) { + CloseXWindow(); + return; + } - gfx::Size adjusted_size_in_pixels = - AdjustSizeForDisplay(config.bounds.size()); - config.bounds.set_size(adjusted_size_in_pixels); - config.override_redirect = - properties.x11_extension_delegate && - properties.x11_extension_delegate->IsOverrideRedirect(IsWmTiling()); - if (config.type == WindowType::kDrag) { - config.opacity = ui::IsCompositingManagerPresent() - ? WindowOpacity::kTranslucentWindow - : WindowOpacity::kOpaqueWindow; + // At this point, the X window is created. Register it and notify the + // platform window delegate. + X11WindowManager::GetInstance()->AddWindow(this); + + connection_->AddEventObserver(this); + DCHECK(X11EventSource::HasInstance()); + X11EventSource::GetInstance()->AddPlatformEventDispatcher(this); + + x11_window_move_client_ = + std::make_unique(this); + + // Mark the window as eligible for the move loop, which allows tab dragging. + SetWmMoveLoopHandler(this, static_cast(this)); + + platform_window_delegate_->OnAcceleratedWidgetAvailable(GetWidget()); + + // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). + + auto event_mask = + x11::EventMask::ButtonPress | x11::EventMask::ButtonRelease | + x11::EventMask::FocusChange | x11::EventMask::KeyPress | + x11::EventMask::KeyRelease | x11::EventMask::EnterWindow | + x11::EventMask::LeaveWindow | x11::EventMask::Exposure | + x11::EventMask::VisibilityChange | x11::EventMask::StructureNotify | + x11::EventMask::PropertyChange | x11::EventMask::PointerMotion; + xwindow_events_ = + std::make_unique(xwindow_, event_mask); + connection_->Flush(); + + if (IsXInput2Available()) + TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); + + // Request the _NET_WM_SYNC_REQUEST protocol which is used for synchronizing + // between chrome and desktop compositor (or WM) during resizing. + // The resizing behavior with _NET_WM_SYNC_REQUEST is: + // 1. Desktop compositor (or WM) sends client message _NET_WM_SYNC_REQUEST + // with a 64 bits counter to notify about an incoming resize. + // 2. Desktop compositor resizes chrome browser window. + // 3. Desktop compositor waits on an alert on value change of XSyncCounter on + // chrome window. + // 4. Chrome handles the ConfigureNotify event, and renders a new frame with + // the new size. + // 5. Chrome increases the XSyncCounter on chrome window + // 6. Desktop compositor gets the alert of counter change, and draws a new + // frame with new content from chrome. + // 7. Desktop compositor responses user mouse move events, and starts a new + // resize process, go to step 1. + std::vector protocols = { + x11::GetAtom("WM_DELETE_WINDOW"), + x11::GetAtom("_NET_WM_PING"), + x11::GetAtom("_NET_WM_SYNC_REQUEST"), + }; + SetArrayProperty(xwindow_, x11::GetAtom("WM_PROTOCOLS"), x11::Atom::ATOM, + protocols); + + // We need a WM_CLIENT_MACHINE value so we integrate with the desktop + // environment. + SetStringProperty(xwindow_, x11::Atom::WM_CLIENT_MACHINE, x11::Atom::STRING, + net::GetHostName()); + + // Likewise, the X server needs to know this window's pid so it knows which + // program to kill if the window hangs. + // XChangeProperty() expects "pid" to be long. + static_assert(sizeof(uint32_t) >= sizeof(pid_t), + "pid_t should not be larger than uint32_t"); + uint32_t pid = getpid(); + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_PID"), x11::Atom::CARDINAL, + pid); + + x11::Atom window_type; + switch (properties.type) { + case PlatformWindowType::kMenu: + window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_MENU"); + break; + case PlatformWindowType::kTooltip: + window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"); + break; + case PlatformWindowType::kPopup: + window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION"); + break; + case PlatformWindowType::kDrag: + window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_DND"); + break; + default: + window_type = x11::GetAtom("_NET_WM_WINDOW_TYPE_NORMAL"); + break; } + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_WINDOW_TYPE"), + x11::Atom::ATOM, window_type); - workspace_extension_delegate_ = properties.workspace_extension_delegate; - x11_extension_delegate_ = properties.x11_extension_delegate; + // The changes to |window_properties_| here will be sent to the X server just + // before the window is mapped. + + // Remove popup windows from taskbar unless overridden. + if ((properties.type == PlatformWindowType::kPopup || + properties.type == PlatformWindowType::kBubble) && + !properties.force_show_in_taskbar) { + window_properties_.insert(x11::GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); + } + + // If the window should stay on top of other windows, add the + // _NET_WM_STATE_ABOVE property. + is_always_on_top_ = properties.keep_on_top; + if (is_always_on_top_) + window_properties_.insert(x11::GetAtom("_NET_WM_STATE_ABOVE")); + + workspace_ = base::nullopt; + if (properties.visible_on_all_workspaces) { + window_properties_.insert(x11::GetAtom("_NET_WM_STATE_STICKY")); + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_DESKTOP"), + x11::Atom::CARDINAL, kAllWorkspaces); + } else if (!properties.workspace.empty()) { + int32_t workspace; + if (base::StringToInt(properties.workspace, &workspace)) + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_DESKTOP"), + x11::Atom::CARDINAL, workspace); + } + + if (!properties.wm_class_name.empty() || !properties.wm_class_class.empty()) { + SetWindowClassHint(connection_, xwindow_, properties.wm_class_name, + properties.wm_class_class); + } + + const char* wm_role_name = nullptr; + // If the widget isn't overriding the role, provide a default value for popup + // and bubble types. + if (!properties.wm_role_name.empty()) { + wm_role_name = properties.wm_role_name.c_str(); + } else { + switch (properties.type) { + case PlatformWindowType::kPopup: + wm_role_name = kX11WindowRolePopup; + break; + case PlatformWindowType::kBubble: + wm_role_name = kX11WindowRoleBubble; + break; + default: + break; + } + } + if (wm_role_name) + SetWindowRole(xwindow_, std::string(wm_role_name)); + + if (properties.remove_standard_frame) { + // Setting _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED tells gnome-shell to not force + // fullscreen on the window when it matches the desktop size. + SetHideTitlebarWhenMaximizedProperty(xwindow_, + HIDE_TITLEBAR_WHEN_MAXIMIZED); + } + + if (properties.prefer_dark_theme) { + SetStringProperty(xwindow_, x11::GetAtom("_GTK_THEME_VARIANT"), + x11::GetAtom("UTF8_STRING"), kDarkGtkThemeVariant); + } + + if (IsSyncExtensionAvailable()) { + x11::Sync::Int64 value{}; + update_counter_ = connection_->GenerateId(); + connection_->sync().CreateCounter({update_counter_, value}); + extended_update_counter_ = connection_->GenerateId(); + connection_->sync().CreateCounter({extended_update_counter_, value}); + + std::vector counters{update_counter_, + extended_update_counter_}; + + // Set XSyncCounter as window property _NET_WM_SYNC_REQUEST_COUNTER. the + // compositor will listen on them during resizing. + SetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_SYNC_REQUEST_COUNTER"), + x11::Atom::CARDINAL, counters); + } + + // Always composite Chromium windows if a compositing WM is used. Sometimes, + // WMs will not composite fullscreen windows as an optimization, but this can + // lead to tearing of fullscreen videos. + x11::SetProperty(xwindow_, + x11::GetAtom("_NET_WM_BYPASS_COMPOSITOR"), + x11::Atom::CARDINAL, 2); - Init(config); + if (properties.icon) + SetWindowIcons(gfx::ImageSkia(), *properties.icon); - if (config.type == WindowType::kDrag && - config.opacity == WindowOpacity::kTranslucentWindow) { + if (properties.type == PlatformWindowType::kDrag && + opacity == PlatformWindowOpacity::kTranslucentWindow) { SetOpacity(kDragWidgetOpacity); } @@ -167,11 +406,6 @@ void X11Window::Initialize(PlatformWindowInitProperties properties) { drag_drop_client_ = std::make_unique(this, window()); } -void X11Window::SetXEventDelegate(XEventDelegate* delegate) { - DCHECK(!x_event_delegate_); - x_event_delegate_ = delegate; -} - void X11Window::OnXWindowLostCapture() { platform_window_delegate_->OnLostCapture(); } @@ -189,14 +423,21 @@ gfx::AcceleratedWidget X11Window::GetWidget() const { } void X11Window::Show(bool inactive) { - if (mapped_in_client()) + if (window_mapped_in_client_) return; - XWindow::Map(inactive); + Map(inactive); } void X11Window::Hide() { - XWindow::Hide(); + if (!window_mapped_in_client_) + return; + + // Make sure no resize task will run after the window is unmapped. + CancelResize(); + + WithdrawWindow(xwindow_); + window_mapped_in_client_ = false; } void X11Window::Close() { @@ -206,61 +447,122 @@ void X11Window::Close() { X11WindowManager::GetInstance()->RemoveWindow(this); is_shutting_down_ = true; - XWindow::Close(); + + CloseXWindow(); + platform_window_delegate_->OnClosed(); } bool X11Window::IsVisible() const { - return XWindow::IsXWindowVisible(); + // On Windows, IsVisible() returns true for minimized windows. On X11, a + // minimized window is not mapped, so an explicit IsMinimized() check is + // necessary. + return window_mapped_in_client_ || IsMinimized(); } void X11Window::PrepareForShutdown() { - connection()->RemoveEventObserver(this); + connection_->RemoveEventObserver(this); DCHECK(X11EventSource::HasInstance()); X11EventSource::GetInstance()->RemovePlatformEventDispatcher(this); } void X11Window::SetBounds(const gfx::Rect& bounds) { - gfx::Rect current_bounds_in_pixels = GetBounds(); - gfx::Rect bounds_in_pixels(bounds.origin(), - AdjustSizeForDisplay(bounds.size())); + gfx::Rect new_bounds_in_pixels(bounds.origin(), + AdjustSizeForDisplay(bounds.size())); - bool size_changed = - current_bounds_in_pixels.size() != bounds_in_pixels.size(); + const bool size_changed = + bounds_in_pixels_.size() != new_bounds_in_pixels.size(); + const bool origin_changed = + bounds_in_pixels_.origin() != new_bounds_in_pixels.origin(); + + // Assume that the resize will go through as requested, which should be the + // case if we're running without a window manager. If there's a window + // manager, it can modify or ignore the request, but (per ICCCM) we'll get a + // (possibly synthetic) ConfigureNotify about the actual size and correct + // |bounds_| later. + + x11::ConfigureWindowRequest req{.window = xwindow_}; if (size_changed) { // Only cancel the delayed resize task if we're already about to call // OnHostResized in this function. - XWindow::CancelResize(); + CancelResize(); + + // Update the minimum and maximum sizes in case they have changed. + UpdateMinAndMaxSize(); + + if (new_bounds_in_pixels.width() < min_size_in_pixels_.width() || + new_bounds_in_pixels.height() < min_size_in_pixels_.height() || + (!max_size_in_pixels_.IsEmpty() && + (new_bounds_in_pixels.width() > max_size_in_pixels_.width() || + new_bounds_in_pixels.height() > max_size_in_pixels_.height()))) { + gfx::Size size_in_pixels = new_bounds_in_pixels.size(); + if (!max_size_in_pixels_.IsEmpty()) + size_in_pixels.SetToMin(max_size_in_pixels_); + size_in_pixels.SetToMax(min_size_in_pixels_); + new_bounds_in_pixels.set_size(size_in_pixels); + } + + req.width = new_bounds_in_pixels.width(); + req.height = new_bounds_in_pixels.height(); } + if (origin_changed) { + req.x = new_bounds_in_pixels.x(); + req.y = new_bounds_in_pixels.y(); + } + + if (origin_changed || size_changed) + connection_->ConfigureWindow(req); + // Assume that the resize will go through as requested, which should be the // case if we're running without a window manager. If there's a window // manager, it can modify or ignore the request, but (per ICCCM) we'll get a // (possibly synthetic) ConfigureNotify about the actual size and correct - // |bounds_| later. - XWindow::SetBounds(bounds_in_pixels); + // |bounds_in_pixels_| later. + bounds_in_pixels_ = new_bounds_in_pixels; + ResetWindowRegion(); + + // Even if the pixel bounds didn't change this call to the delegate should + // still happen. The device scale factor may have changed which effectively + // changes the bounds. + OnXWindowBoundsChanged(new_bounds_in_pixels); } gfx::Rect X11Window::GetBounds() const { - return XWindow::bounds(); + return bounds_in_pixels_; } -void X11Window::SetTitle(const base::string16& title) { - XWindow::SetTitle(title); +void X11Window::SetTitle(const std::u16string& title) { + if (window_title_ == title) + return; + + window_title_ = title; + std::string utf8str = base::UTF16ToUTF8(title); + SetStringProperty(xwindow_, x11::GetAtom("_NET_WM_NAME"), + x11::GetAtom("UTF8_STRING"), utf8str); + SetStringProperty(xwindow_, x11::Atom::WM_NAME, x11::GetAtom("UTF8_STRING"), + utf8str); } void X11Window::SetCapture() { if (HasCapture()) return; X11WindowManager::GetInstance()->GrabEvents(this); - GrabPointer(); + + // If the pointer is already in |xwindow_|, we will not get a crossing event + // with a mode of NotifyGrab, so we must record the grab state manually. + has_pointer_grab_ |= + (ui::GrabPointer(xwindow_, true, nullptr) == x11::GrabStatus::Success); } void X11Window::ReleaseCapture() { if (!HasCapture()) return; - ReleasePointerGrab(); + + UngrabPointer(); + has_pointer_grab_ = false; + X11WindowManager::GetInstance()->UngrabEvents(this); } @@ -308,13 +610,12 @@ void X11Window::ToggleFullscreen() { // - works around Flash content which expects to have the size updated // synchronously. // See https://crbug.com/361408 - gfx::Rect bounds_in_pixels = GetBounds(); + gfx::Rect new_bounds_px = GetBounds(); if (fullscreen) { display::Screen* screen = display::Screen::GetScreen(); - const display::Display display = - screen->GetDisplayMatching(bounds_in_pixels); - SetRestoredBoundsInPixels(bounds_in_pixels); - bounds_in_pixels = + const display::Display display = screen->GetDisplayMatching(new_bounds_px); + SetRestoredBoundsInPixels(new_bounds_px); + new_bounds_px = gfx::Rect(gfx::ScaleToFlooredPoint(display.bounds().origin(), display.device_scale_factor()), display.GetSizeInPixel()); @@ -325,15 +626,15 @@ void X11Window::ToggleFullscreen() { // before trying to restore its bounds (saved before entering in browser // fullscreen mode). if (was_fullscreen) - bounds_in_pixels = GetRestoredBoundsInPixels(); + new_bounds_px = GetRestoredBoundsInPixels(); else SetRestoredBoundsInPixels({}); } // Do not go through SetBounds as long as it adjusts bounds and sets them to X // Server. Instead, we just store the bounds and notify the client that the // window occupies the entire screen. - XWindow::set_bounds(bounds_in_pixels); - platform_window_delegate_->OnBoundsChanged(bounds_in_pixels); + bounds_in_pixels_ = new_bounds_px; + platform_window_delegate_->OnBoundsChanged(new_bounds_px); } void X11Window::Maximize() { @@ -357,16 +658,28 @@ void X11Window::Maximize() { // heuristics that are in the PropertyNotify and ConfigureNotify handlers. SetRestoredBoundsInPixels(GetBounds()); - XWindow::Maximize(); + // Some WMs do not respect maximization hints on unmapped windows, so we + // save this one for later too. + should_maximize_after_map_ = !window_mapped_in_client_; + + SetWMSpecState(true, x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), + x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")); } void X11Window::Minimize() { - XWindow::Minimize(); + if (window_mapped_in_client_) { + SendClientMessage(xwindow_, x_root_window_, x11::GetAtom("WM_CHANGE_STATE"), + {WM_STATE_ICONIC, 0, 0, 0, 0}); + } else { + SetWMSpecState(true, x11::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None); + } } void X11Window::Restore() { - XWindow::Unmaximize(); - XWindow::Unhide(); + should_maximize_after_map_ = false; + SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), + x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")); + SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None); } PlatformWindowState X11Window::GetPlatformWindowState() const { @@ -374,31 +687,128 @@ PlatformWindowState X11Window::GetPlatformWindowState() const { } void X11Window::Activate() { - XWindow::Activate(); + if (!IsVisible() || !activatable_) + return; + + BeforeActivationStateChanged(); + + ignore_keyboard_input_ = false; + + // wmii says that it supports _NET_ACTIVE_WINDOW but does not. + // https://code.google.com/p/wmii/issues/detail?id=266 + static bool wm_supports_active_window = + GuessWindowManager() != WM_WMII && + WmSupportsHint(x11::GetAtom("_NET_ACTIVE_WINDOW")); + + x11::Time timestamp = X11EventSource::GetInstance()->GetTimestamp(); + + // override_redirect windows ignore _NET_ACTIVE_WINDOW. + // https://crbug.com/940924 + if (wm_supports_active_window && !override_redirect_) { + std::array data = { + // We're an app. + 1, + static_cast(timestamp), + // TODO(thomasanderson): if another chrome window is active, specify + // that here. The EWMH spec claims this may make the WM more likely to + // service our _NET_ACTIVE_WINDOW request. + 0, + 0, + 0, + }; + SendClientMessage(xwindow_, x_root_window_, + x11::GetAtom("_NET_ACTIVE_WINDOW"), data); + } else { + RaiseWindow(xwindow_); + // Directly ask the X server to give focus to the window. Note that the call + // would have raised an X error if the window is not mapped. + connection_ + ->SetInputFocus({x11::InputFocus::Parent, xwindow_, + static_cast(timestamp)}) + .IgnoreError(); + // At this point, we know we will receive focus, and some webdriver tests + // depend on a window being IsActive() immediately after an Activate(), so + // just set this state now. + has_pointer_focus_ = false; + has_window_focus_ = true; + window_mapped_in_server_ = true; + } + + AfterActivationStateChanged(); } void X11Window::Deactivate() { - XWindow::Deactivate(); + BeforeActivationStateChanged(); + + // Ignore future input events. + ignore_keyboard_input_ = true; + + ui::LowerWindow(xwindow_); + + AfterActivationStateChanged(); } void X11Window::SetUseNativeFrame(bool use_native_frame) { - XWindow::SetUseNativeFrame(use_native_frame); + use_native_frame_ = use_native_frame; + SetUseOSWindowFrame(xwindow_, use_native_frame); + ResetWindowRegion(); } bool X11Window::ShouldUseNativeFrame() const { - return XWindow::use_native_frame(); + return use_native_frame_; } void X11Window::SetCursor(PlatformCursor cursor) { - XWindow::SetCursor(static_cast(cursor)); + DCHECK(cursor); + + last_cursor_ = static_cast(cursor); + on_cursor_loaded_.Reset(base::BindOnce(DefineCursor, xwindow_)); + last_cursor_->OnCursorLoaded(on_cursor_loaded_.callback()); } -void X11Window::MoveCursorTo(const gfx::Point& location) { - XWindow::MoveCursorTo(location); +void X11Window::MoveCursorTo(const gfx::Point& location_px) { + connection_->WarpPointer(x11::WarpPointerRequest{ + .dst_window = x_root_window_, + .dst_x = bounds_in_pixels_.x() + location_px.x(), + .dst_y = bounds_in_pixels_.y() + location_px.y(), + }); } void X11Window::ConfineCursorToBounds(const gfx::Rect& bounds) { - XWindow::ConfineCursorTo(bounds); + UnconfineCursor(); + + if (bounds.IsEmpty()) + return; + + gfx::Rect barrier = bounds + bounds_in_pixels_.OffsetFromOrigin(); + + auto make_barrier = [&](uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, + x11::XFixes::BarrierDirections directions) { + x11::XFixes::Barrier barrier = + connection_->GenerateId(); + connection_->xfixes().CreatePointerBarrier( + {barrier, x_root_window_, x1, y1, x2, y2, directions}); + return barrier; + }; + + // Top horizontal barrier. + pointer_barriers_[0] = + make_barrier(barrier.x(), barrier.y(), barrier.right(), barrier.y(), + x11::XFixes::BarrierDirections::PositiveY); + // Bottom horizontal barrier. + pointer_barriers_[1] = + make_barrier(barrier.x(), barrier.bottom(), barrier.right(), + barrier.bottom(), x11::XFixes::BarrierDirections::NegativeY); + // Left vertical barrier. + pointer_barriers_[2] = + make_barrier(barrier.x(), barrier.y(), barrier.x(), barrier.bottom(), + x11::XFixes::BarrierDirections::PositiveX); + // Right vertical barrier. + pointer_barriers_[3] = + make_barrier(barrier.right(), barrier.y(), barrier.right(), + barrier.bottom(), x11::XFixes::BarrierDirections::NegativeX); + + has_pointer_barriers_ = true; } void X11Window::SetRestoredBoundsInPixels(const gfx::Rect& bounds) { @@ -410,7 +820,7 @@ gfx::Rect X11Window::GetRestoredBoundsInPixels() const { } bool X11Window::ShouldWindowContentsBeTransparent() const { - return XWindow::has_alpha(); + return visual_has_alpha_; } void X11Window::SetZOrderLevel(ZOrderLevel order) { @@ -419,51 +829,131 @@ void X11Window::SetZOrderLevel(ZOrderLevel order) { // Emulate the multiple window levels provided by other platforms by // collapsing the z-order enum into kNormal = normal, everything else = always // on top. - XWindow::SetAlwaysOnTop(order != ui::ZOrderLevel::kNormal); + is_always_on_top_ = (z_order_ != ui::ZOrderLevel::kNormal); + SetWMSpecState(is_always_on_top_, x11::GetAtom("_NET_WM_STATE_ABOVE"), + x11::Atom::None); } ZOrderLevel X11Window::GetZOrderLevel() const { - bool window_always_on_top = is_always_on_top(); bool level_always_on_top = z_order_ != ui::ZOrderLevel::kNormal; - if (window_always_on_top == level_always_on_top) + if (is_always_on_top_ == level_always_on_top) return z_order_; // If something external has forced a window to be always-on-top, map it to // kFloatingWindow as a reasonable equivalent. - return window_always_on_top ? ui::ZOrderLevel::kFloatingWindow - : ui::ZOrderLevel::kNormal; + return is_always_on_top_ ? ui::ZOrderLevel::kFloatingWindow + : ui::ZOrderLevel::kNormal; } void X11Window::StackAbove(gfx::AcceleratedWidget widget) { // Check comment in the GetWidget method about this cast. - XWindow::StackXWindowAbove(static_cast(widget)); + auto window = static_cast(widget); + DCHECK(window != x11::Window::None); + + // Find all parent windows up to the root. + std::vector window_below_parents = + GetParentsList(connection_, window); + std::vector window_above_parents = + GetParentsList(connection_, xwindow_); + + // Find their common ancestor. + auto it_below_window = window_below_parents.rbegin(); + auto it_above_window = window_above_parents.rbegin(); + for (; it_below_window != window_below_parents.rend() && + it_above_window != window_above_parents.rend() && + *it_below_window == *it_above_window; + ++it_below_window, ++it_above_window) { + } + + if (it_below_window != window_below_parents.rend() && + it_above_window != window_above_parents.rend()) { + connection_->ConfigureWindow(x11::ConfigureWindowRequest{ + .window = *it_above_window, + .sibling = *it_below_window, + .stack_mode = x11::StackMode::Above, + }); + } } void X11Window::StackAtTop() { - XWindow::StackXWindowAtTop(); + RaiseWindow(xwindow_); } void X11Window::FlashFrame(bool flash_frame) { - XWindow::SetFlashFrameHint(flash_frame); + SetFlashFrameHint(flash_frame); } void X11Window::SetShape(std::unique_ptr native_shape, const gfx::Transform& transform) { - return XWindow::SetXWindowShape(std::move(native_shape), transform); + std::unique_ptr> xregion; + if (native_shape) { + SkRegion native_region; + for (const gfx::Rect& rect : *native_shape) + native_region.op(gfx::RectToSkIRect(rect), SkRegion::kUnion_Op); + if (!transform.IsIdentity() && !native_region.isEmpty()) { + SkPath path_in_dip; + if (native_region.getBoundaryPath(&path_in_dip)) { + SkPath path_in_pixels; + path_in_dip.transform(SkMatrix(transform.matrix()), &path_in_pixels); + xregion = x11::CreateRegionFromSkPath(path_in_pixels); + } else { + xregion = std::make_unique>(); + } + } else { + xregion = x11::CreateRegionFromSkRegion(native_region); + } + } + + custom_window_shape_ = !!xregion; + window_shape_ = std::move(xregion); + ResetWindowRegion(); } void X11Window::SetAspectRatio(const gfx::SizeF& aspect_ratio) { - XWindow::SetXWindowAspectRatio(aspect_ratio); + SizeHints size_hints; + memset(&size_hints, 0, sizeof(size_hints)); + + GetWmNormalHints(xwindow_, &size_hints); + // Unforce aspect ratio is parameter length is 0, otherwise set normally. + if (aspect_ratio.IsEmpty()) { + size_hints.flags &= ~SIZE_HINT_P_ASPECT; + } else { + size_hints.flags |= SIZE_HINT_P_ASPECT; + size_hints.min_aspect_num = size_hints.max_aspect_num = + aspect_ratio.width(); + size_hints.min_aspect_den = size_hints.max_aspect_den = + aspect_ratio.height(); + } + SetWmNormalHints(xwindow_, size_hints); } void X11Window::SetWindowIcons(const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) { - XWindow::SetXWindowIcons(window_icon, app_icon); + // TODO(erg): The way we handle icons across different versions of chrome + // could be substantially improved. The Windows version does its own thing + // and only sometimes comes down this code path. The icon stuff in + // ChromeViewsDelegate is hard coded to use HICONs. Likewise, we're hard + // coded to be given two images instead of an arbitrary collection of images + // so that we can pass to the WM. + // + // All of this could be made much, much better. + std::vector data; + + if (!window_icon.isNull()) + SerializeImageRepresentation(window_icon.GetRepresentation(1.0f), &data); + + if (!app_icon.isNull()) + SerializeImageRepresentation(app_icon.GetRepresentation(1.0f), &data); + + if (!data.empty()) { + SetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_ICON"), + x11::Atom::CARDINAL, data); + } } void X11Window::SizeConstraintsChanged() { - XWindow::UpdateMinAndMaxSize(); + X11Window::UpdateMinAndMaxSize(); } bool X11Window::IsTranslucentWindowOpacitySupported() const { @@ -474,21 +964,53 @@ bool X11Window::IsTranslucentWindowOpacitySupported() const { } void X11Window::SetOpacity(float opacity) { - XWindow::SetXWindowOpacity(opacity); + // X server opacity is in terms of 32 bit unsigned int space, and counts from + // the opposite direction. + // XChangeProperty() expects "cardinality" to be long. + + // Scale opacity to [0 .. 255] range. + uint32_t opacity_8bit = static_cast(opacity * 255.0f) & 0xFF; + // Use opacity value for all channels. + uint32_t channel_multiplier = 0x1010101; + uint32_t cardinality = opacity_8bit * channel_multiplier; + + if (cardinality == 0xffffffff) { + x11::DeleteProperty(xwindow_, x11::GetAtom("_NET_WM_WINDOW_OPACITY")); + } else { + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_WINDOW_OPACITY"), + x11::Atom::CARDINAL, cardinality); + } } std::string X11Window::GetWorkspace() const { - base::Optional workspace_id = XWindow::workspace(); + base::Optional workspace_id = workspace_; return workspace_id.has_value() ? base::NumberToString(workspace_id.value()) : std::string(); } void X11Window::SetVisibleOnAllWorkspaces(bool always_visible) { - XWindow::SetXWindowVisibleOnAllWorkspaces(always_visible); + SetWMSpecState(always_visible, x11::GetAtom("_NET_WM_STATE_STICKY"), + x11::Atom::None); + + int new_desktop = 0; + if (always_visible) { + new_desktop = kAllWorkspaces; + } else { + if (!GetCurrentDesktop(&new_desktop)) + return; + } + + workspace_ = kAllWorkspaces; + SendClientMessage(xwindow_, x_root_window_, x11::GetAtom("_NET_WM_DESKTOP"), + {new_desktop, 0, 0, 0, 0}); } bool X11Window::IsVisibleOnAllWorkspaces() const { - return XWindow::IsXWindowVisibleOnAllWorkspaces(); + // We don't need a check for _NET_WM_STATE_STICKY because that would specify + // that the window remain in a fixed position even if the viewport scrolls. + // This is different from the type of workspace that's associated with + // _NET_WM_DESKTOP. + return workspace_ == kAllWorkspaces; } void X11Window::SetWorkspaceExtensionDelegate( @@ -505,23 +1027,57 @@ bool X11Window::IsWmTiling() const { } void X11Window::OnCompleteSwapAfterResize() { - XWindow::NotifySwapAfterResize(); + if (configure_counter_value_is_extended_) { + if ((current_counter_value_ % 2) == 1) { + // An increase 3 means that the frame was not drawn as fast as possible. + // This can trigger different handling from the compositor. + // Setting an even number to |extended_update_counter_| will trigger a + // new resize. + current_counter_value_ += 3; + SyncSetCounter(connection_, extended_update_counter_, + current_counter_value_); + } + return; + } + + if (configure_counter_value_ != 0) { + SyncSetCounter(connection_, update_counter_, configure_counter_value_); + configure_counter_value_ = 0; + } } gfx::Rect X11Window::GetXRootWindowOuterBounds() const { - return XWindow::GetOuterBounds(); + return GetOuterBounds(); } bool X11Window::ContainsPointInXRegion(const gfx::Point& point) const { - return XWindow::ContainsPointInRegion(point); + if (!shape()) + return true; + + for (const auto& rect : *shape()) { + if (gfx::Rect(rect.x, rect.y, rect.width, rect.height).Contains(point)) + return true; + } + return false; } void X11Window::LowerXWindow() { - XWindow::LowerWindow(); + ui::LowerWindow(xwindow_); } void X11Window::SetOverrideRedirect(bool override_redirect) { - XWindow::SetOverrideRedirect(override_redirect); + bool remap = window_mapped_in_client_; + if (remap) + Hide(); + connection_->ChangeWindowAttributes(x11::ChangeWindowAttributesRequest{ + .window = xwindow_, + .override_redirect = x11::Bool32(override_redirect), + }); + if (remap) { + Map(); + if (has_pointer_grab_) + ChangeActivePointerGrabCursor(nullptr); + } } void X11Window::SetX11ExtensionDelegate(X11ExtensionDelegate* delegate) { @@ -549,16 +1105,15 @@ void X11Window::OnEvent(const x11::Event& xev) { target_current_context->DispatchPropertyNotifyEvent(*prop); } - if (XWindow::IsTargetedBy(xev)) - XWindow::OnEvent(xev); + HandleEvent(xev); } bool X11Window::CanDispatchEvent(const PlatformEvent& xev) { if (is_shutting_down_) return false; DCHECK_NE(window(), x11::Window::None); - auto* dispatching_event = connection()->dispatching_event(); - return dispatching_event && XWindow::IsTargetedBy(*dispatching_event); + auto* dispatching_event = connection_->dispatching_event(); + return dispatching_event && IsTargetedBy(*dispatching_event); } uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { @@ -568,16 +1123,15 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) { DCHECK_NE(window(), x11::Window::None); DCHECK(event); - auto& current_xevent = *connection()->dispatching_event(); + auto& current_xevent = *connection_->dispatching_event(); if (event->IsMouseEvent()) X11WindowManager::GetInstance()->MouseOnWindow(this); #if BUILDFLAG(USE_ATK) - // TODO(crbug.com/1014934): Support ATK in Ozone/X11. - bool current_xevent_target_transient = - XWindow::IsTransientWindowTargetedBy(current_xevent); - if (HandleAsAtkEvent(current_xevent, current_xevent_target_transient)) + if (HandleAsAtkEvent(current_xevent, + current_xevent.window() == transient_window_)) { return POST_DISPATCH_STOP_PROPAGATION; + } #endif DispatchUiEvent(event, current_xevent); @@ -589,8 +1143,7 @@ void X11Window::DispatchUiEvent(ui::Event* event, const x11::Event& xev) { DCHECK(window_manager); // Process X11-specific bits - if (XWindow::IsTargetedBy(xev)) - XWindow::OnEvent(xev); + HandleEvent(xev); // If |event| is a located event (mouse, touch, etc) and another X11 window // is set as the current located events grabber, the |event| must be @@ -623,7 +1176,7 @@ void X11Window::DispatchUiEvent(ui::Event* event, const x11::Event& xev) { // Linux are checked with cmt-device path, and can include DT_CMT_SCROLL_ // data. See more discussion in https://crrev.com/c/853953 if (event) { - XWindow::UpdateWMUserTime(event); + UpdateWMUserTime(event); bool event_dispatched = false; #if defined(USE_OZONE) if (features::IsUsingOzonePlatform()) { @@ -640,23 +1193,6 @@ void X11Window::DispatchUiEvent(ui::Event* event, const x11::Event& xev) { } } -void X11Window::OnXWindowCreated() { - X11WindowManager::GetInstance()->AddWindow(this); - - connection()->AddEventObserver(this); - DCHECK(X11EventSource::HasInstance()); - X11EventSource::GetInstance()->AddPlatformEventDispatcher(this); - - x11_window_move_client_ = - std::make_unique(this); - - // Set a class property key, which allows |this| to be used for move loop aka - // tab dragging. - SetWmMoveLoopHandler(this, static_cast(this)); - - platform_window_delegate_->OnAcceleratedWidgetAvailable(GetWidget()); -} - void X11Window::OnXWindowStateChanged() { // Determine the new window state information to be propagated to the client. // Note that the order of checks is important here, because window can have @@ -701,7 +1237,7 @@ void X11Window::OnXWindowStateChanged() { // a best effort attempt to get restored bounds by setting it to our // previously set bounds (and if we get this wrong, we aren't any worse // off since we'd otherwise be returning our maximized bounds). - SetRestoredBoundsInPixels(previous_bounds()); + SetRestoredBoundsInPixels(previous_bounds_in_pixels_); } } else if (!IsMaximized() && !IsFullscreen()) { // If we have restored bounds, but WM_STATE no longer claims to be @@ -742,15 +1278,11 @@ void X11Window::OnXWindowLostPointerGrab() { } void X11Window::OnXWindowSelectionEvent(const x11::SelectionNotifyEvent& xev) { - if (x_event_delegate_) - x_event_delegate_->OnXWindowSelectionEvent(xev); DCHECK(drag_drop_client_); drag_drop_client_->OnSelectionNotify(xev); } void X11Window::OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev) { - if (x_event_delegate_) - x_event_delegate_->OnXWindowDragDropEvent(xev); DCHECK(drag_drop_client_); drag_drop_client_->HandleXdndEvent(xev); } @@ -770,7 +1302,12 @@ SkPath X11Window::GetWindowMaskForXWindow() { void X11Window::DispatchHostWindowDragMovement( int hittest, const gfx::Point& pointer_location_in_px) { - XWindow::WmMoveResize(hittest, pointer_location_in_px); + int direction = HitTestToWmMoveResizeDirection(hittest); + if (direction == -1) + return; + + DoWMMoveResize(connection_, x_root_window_, xwindow_, pointer_location_in_px, + direction); } bool X11Window::RunMoveLoop(const gfx::Vector2d& drag_offset) { @@ -798,7 +1335,7 @@ bool X11Window::StartDrag(const OSExchangeData& data, auto alive = weak_ptr_factory_.GetWeakPtr(); const bool dropped = - drag_loop_->RunMoveLoop(can_grab_pointer, last_cursor(), last_cursor()); + drag_loop_->RunMoveLoop(can_grab_pointer, last_cursor_, last_cursor_); if (!alive) return false; @@ -915,6 +1452,18 @@ void X11Window::OnMoveLoopEnded() { drag_drop_client_->HandleMoveLoopEnded(); } +void X11Window::SetBoundsOnMove(const gfx::Rect& requested_bounds) { + SetBounds(requested_bounds); +} + +scoped_refptr X11Window::GetLastCursor() { + return last_cursor_; +} + +gfx::Size X11Window::GetSize() { + return bounds_in_pixels_.size(); +} + void X11Window::QuitDragLoop() { DCHECK(drag_loop_); drag_loop_->EndMoveLoop(); @@ -966,4 +1515,797 @@ void X11Window::ConvertEventLocationToTargetLocation( located_event); } +void X11Window::CreateXWindow(const PlatformWindowInitProperties& properties, + PlatformWindowOpacity& opacity) { + 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; + + // Ensure that the X11MenuRegistrar exists. The X11MenuRegistrar is + // necessary to properly track menu windows. + X11MenuRegistrar::Get(); + + activatable_ = properties.activatable; + + x11::CreateWindowRequest req; + req.bit_gravity = x11::Gravity::NorthWest; + req.background_pixel = properties.background_color.has_value() + ? properties.background_color.value() + : connection_->default_screen().white_pixel; + + switch (properties.type) { + case PlatformWindowType::kMenu: + req.override_redirect = x11::Bool32(true); + break; + case PlatformWindowType::kTooltip: + req.override_redirect = x11::Bool32(true); + break; + case PlatformWindowType::kPopup: + req.override_redirect = x11::Bool32(true); + break; + case PlatformWindowType::kDrag: + req.override_redirect = x11::Bool32(true); + break; + default: + break; + } + // An in-activatable window should not interact with the system wm. + if (!activatable_ || override_redirect) + req.override_redirect = x11::Bool32(true); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + req.override_redirect = x11::Bool32(UseTestConfigForPlatformWindows()); +#endif + + override_redirect_ = req.override_redirect.has_value(); + + bool enable_transparent_visuals; + switch (opacity) { + case PlatformWindowOpacity::kOpaqueWindow: + enable_transparent_visuals = false; + break; + case PlatformWindowOpacity::kTranslucentWindow: + enable_transparent_visuals = true; + break; + case PlatformWindowOpacity::kInferOpacity: + enable_transparent_visuals = properties.type == PlatformWindowType::kDrag; + } + + if (properties.wm_role_name == kStatusIconWmRoleName) { + std::string atom_name = + "_NET_SYSTEM_TRAY_S" + + base::NumberToString(connection_->DefaultScreenId()); + auto selection = connection_->GetSelectionOwner({x11::GetAtom(atom_name)}); + if (auto reply = selection.Sync()) { + x11::GetProperty(reply->owner, x11::GetAtom("_NET_SYSTEM_TRAY_VISUAL"), + &visual_id_); + } + } + + x11::VisualId visual_id = visual_id_; + uint8_t depth = 0; + x11::ColorMap colormap{}; + XVisualManager* visual_manager = XVisualManager::GetInstance(); + if (visual_id_ == x11::VisualId{} || + !visual_manager->GetVisualInfo(visual_id_, &depth, &colormap, + &visual_has_alpha_)) { + visual_manager->ChooseVisualForWindow(enable_transparent_visuals, + &visual_id, &depth, &colormap, + &visual_has_alpha_); + } + + // x.org will BadMatch if we don't set a border when the depth isn't the + // same as the parent depth. + req.border_pixel = 0; + + bounds_in_pixels_ = SanitizeBounds(bounds); + req.parent = x_root_window_; + req.x = bounds_in_pixels_.x(); + req.y = bounds_in_pixels_.y(); + req.width = bounds_in_pixels_.width(); + req.height = bounds_in_pixels_.height(); + req.depth = depth; + req.c_class = x11::WindowClass::InputOutput; + req.visual = visual_id; + req.colormap = colormap; + xwindow_ = connection_->GenerateId(); + req.wid = xwindow_; + connection_->CreateWindow(req); +} + +void X11Window::CloseXWindow() { + if (xwindow_ == x11::Window::None) + return; + + CancelResize(); + UnconfineCursor(); + + connection_->DestroyWindow({xwindow_}); + xwindow_ = x11::Window::None; + + if (update_counter_ != x11::Sync::Counter{}) { + connection_->sync().DestroyCounter({update_counter_}); + connection_->sync().DestroyCounter({extended_update_counter_}); + update_counter_ = {}; + extended_update_counter_ = {}; + } +} + +void X11Window::Map(bool inactive) { + // Before we map the window, set size hints. Otherwise, some window managers + // will ignore toplevel XMoveWindow commands. + SizeHints size_hints; + memset(&size_hints, 0, sizeof(size_hints)); + GetWmNormalHints(xwindow_, &size_hints); + size_hints.flags |= SIZE_HINT_P_POSITION; + size_hints.x = bounds_in_pixels_.x(); + size_hints.y = bounds_in_pixels_.y(); + SetWmNormalHints(xwindow_, size_hints); + + ignore_keyboard_input_ = inactive; + auto wm_user_time_ms = ignore_keyboard_input_ + ? x11::Time::CurrentTime + : X11EventSource::GetInstance()->GetTimestamp(); + if (inactive || wm_user_time_ms != x11::Time::CurrentTime) { + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_USER_TIME"), + x11::Atom::CARDINAL, wm_user_time_ms); + } + + UpdateMinAndMaxSize(); + + if (window_properties_.empty()) { + x11::DeleteProperty(xwindow_, x11::GetAtom("_NET_WM_STATE")); + } else { + SetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_STATE"), x11::Atom::ATOM, + std::vector(std::begin(window_properties_), + std::end(window_properties_))); + } + + connection_->MapWindow({xwindow_}); + window_mapped_in_client_ = true; + + // TODO(thomasanderson): Find out why this flush is necessary. + connection_->Flush(); +} + +void X11Window::SetFullscreen(bool fullscreen) { + SetWMSpecState(fullscreen, x11::GetAtom("_NET_WM_STATE_FULLSCREEN"), + x11::Atom::None); +} + +bool X11Window::IsActive() const { + // Focus and stacking order are independent in X11. Since we cannot guarantee + // a window is topmost iff it has focus, just use the focus state to determine + // if a window is active. Note that Activate() and Deactivate() change the + // stacking order in addition to changing the focus state. + return (has_window_focus_ || has_pointer_focus_) && !ignore_keyboard_input_; +} + +bool X11Window::IsMinimized() const { + return HasWMSpecProperty(window_properties_, + x11::GetAtom("_NET_WM_STATE_HIDDEN")); +} + +bool X11Window::IsMaximized() const { + return (HasWMSpecProperty(window_properties_, + x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) && + HasWMSpecProperty(window_properties_, + x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"))); +} + +bool X11Window::IsFullscreen() const { + return HasWMSpecProperty(window_properties_, + x11::GetAtom("_NET_WM_STATE_FULLSCREEN")); +} + +gfx::Rect X11Window::GetOuterBounds() const { + gfx::Rect outer_bounds(bounds_in_pixels_); + outer_bounds.Inset(-native_window_frame_borders_in_pixels_); + return outer_bounds; +} + +void X11Window::ResetWindowRegion() { + std::unique_ptr> xregion; + if (!custom_window_shape_ && !IsMaximized() && !IsFullscreen()) { + SkPath window_mask = GetWindowMaskForXWindow(); + // Some frame views define a custom (non-rectangular) window mask. If + // so, use it to define the window shape. If not, fall through. + if (window_mask.countPoints() > 0) + xregion = x11::CreateRegionFromSkPath(window_mask); + } + UpdateWindowRegion(std::move(xregion)); +} + +void X11Window::OnWorkspaceUpdated() { + auto old_workspace = workspace_; + int workspace; + if (GetWindowDesktop(xwindow_, &workspace)) + workspace_ = workspace; + else + workspace_ = base::nullopt; + + if (workspace_ != old_workspace) + OnXWindowWorkspaceChanged(); +} + +void X11Window::SetFlashFrameHint(bool flash_frame) { + if (urgency_hint_set_ == flash_frame) + return; + + WmHints hints; + memset(&hints, 0, sizeof(hints)); + GetWmHints(xwindow_, &hints); + + if (flash_frame) + hints.flags |= WM_HINT_X_URGENCY; + else + hints.flags &= ~WM_HINT_X_URGENCY; + + SetWmHints(xwindow_, hints); + + urgency_hint_set_ = flash_frame; +} + +void X11Window::UpdateMinAndMaxSize() { + base::Optional minimum_in_pixels = GetMinimumSizeForXWindow(); + base::Optional 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())) + return; + + min_size_in_pixels_ = minimum_in_pixels.value(); + max_size_in_pixels_ = maximum_in_pixels.value(); + + SizeHints hints; + memset(&hints, 0, sizeof(hints)); + GetWmNormalHints(xwindow_, &hints); + + if (min_size_in_pixels_.IsEmpty()) { + hints.flags &= ~SIZE_HINT_P_MIN_SIZE; + } else { + hints.flags |= SIZE_HINT_P_MIN_SIZE; + hints.min_width = min_size_in_pixels_.width(); + hints.min_height = min_size_in_pixels_.height(); + } + + if (max_size_in_pixels_.IsEmpty()) { + hints.flags &= ~SIZE_HINT_P_MAX_SIZE; + } else { + hints.flags |= SIZE_HINT_P_MAX_SIZE; + hints.max_width = max_size_in_pixels_.width(); + hints.max_height = max_size_in_pixels_.height(); + } + + SetWmNormalHints(xwindow_, hints); +} + +void X11Window::BeforeActivationStateChanged() { + was_active_ = IsActive(); + had_pointer_ = has_pointer_; + had_pointer_grab_ = has_pointer_grab_; + had_window_focus_ = has_window_focus_; +} + +void X11Window::AfterActivationStateChanged() { + if (had_pointer_grab_ && !has_pointer_grab_) + OnXWindowLostPointerGrab(); + + bool had_pointer_capture = had_pointer_ || had_pointer_grab_; + bool has_pointer_capture = has_pointer_ || has_pointer_grab_; + if (had_pointer_capture && !has_pointer_capture) + OnXWindowLostCapture(); + + bool is_active = IsActive(); + if (!was_active_ && is_active) + SetFlashFrameHint(false); + + if (was_active_ != is_active) + OnXWindowIsActiveChanged(is_active); +} + +void X11Window::OnCrossingEvent(bool enter, + bool focus_in_window_or_ancestor, + x11::NotifyMode mode, + x11::NotifyDetail detail) { + // NotifyInferior on a crossing event means the pointer moved into or out of a + // child window, but the pointer is still within |xwindow_|. + if (detail == x11::NotifyDetail::Inferior) + return; + + BeforeActivationStateChanged(); + + if (mode == x11::NotifyMode::Grab) + has_pointer_grab_ = enter; + else if (mode == x11::NotifyMode::Ungrab) + has_pointer_grab_ = false; + + has_pointer_ = enter; + if (focus_in_window_or_ancestor && !has_window_focus_) { + // If we reach this point, we know the focus is in an ancestor or the + // pointer root. The definition of |has_pointer_focus_| is (An ancestor + // window or the PointerRoot is focused) && |has_pointer_|. Therefore, we + // can just use |has_pointer_| in the assignment. The transitions for when + // the focus changes are handled in OnFocusEvent(). + has_pointer_focus_ = has_pointer_; + } + + AfterActivationStateChanged(); +} + +void X11Window::OnFocusEvent(bool focus_in, + x11::NotifyMode mode, + x11::NotifyDetail detail) { + // NotifyInferior on a focus event means the focus moved into or out of a + // child window, but the focus is still within |xwindow_|. + if (detail == x11::NotifyDetail::Inferior) + return; + + bool notify_grab = + mode == x11::NotifyMode::Grab || mode == x11::NotifyMode::Ungrab; + + BeforeActivationStateChanged(); + + // For every focus change, the X server sends normal focus events which are + // useful for tracking |has_window_focus_|, but supplements these events with + // NotifyPointer events which are only useful for tracking pointer focus. + + // For |has_pointer_focus_| and |has_window_focus_|, we continue tracking + // state during a grab, but ignore grab/ungrab events themselves. + if (!notify_grab && detail != x11::NotifyDetail::Pointer) + has_window_focus_ = focus_in; + + if (!notify_grab && has_pointer_) { + switch (detail) { + case x11::NotifyDetail::Ancestor: + case x11::NotifyDetail::Virtual: + // If we reach this point, we know |has_pointer_| was true before and + // after this event. Since the definition of |has_pointer_focus_| is + // (An ancestor window or the PointerRoot is focused) && |has_pointer_|, + // we only need to worry about transitions on the first conjunct. + // Therefore, |has_pointer_focus_| will become true when: + // 1. Focus moves from |xwindow_| to an ancestor + // (FocusOut with NotifyAncestor) + // 2. Focus moves from a descendant of |xwindow_| to an ancestor + // (FocusOut with NotifyVirtual) + // |has_pointer_focus_| will become false when: + // 1. Focus moves from an ancestor to |xwindow_| + // (FocusIn with NotifyAncestor) + // 2. Focus moves from an ancestor to a child of |xwindow_| + // (FocusIn with NotifyVirtual) + has_pointer_focus_ = !focus_in; + break; + case x11::NotifyDetail::Pointer: + // The remaining cases for |has_pointer_focus_| becoming true are: + // 3. Focus moves from |xwindow_| to the PointerRoot + // 4. Focus moves from a descendant of |xwindow_| to the PointerRoot + // 5. Focus moves from None to the PointerRoot + // 6. Focus moves from Other to the PointerRoot + // 7. Focus moves from None to an ancestor of |xwindow_| + // 8. Focus moves from Other to an ancestor of |xwindow_| + // In each case, we will get a FocusIn with a detail of NotifyPointer. + // The remaining cases for |has_pointer_focus_| becoming false are: + // 3. Focus moves from the PointerRoot to |xwindow_| + // 4. Focus moves from the PointerRoot to a descendant of |xwindow| + // 5. Focus moves from the PointerRoot to None + // 6. Focus moves from an ancestor of |xwindow_| to None + // 7. Focus moves from the PointerRoot to Other + // 8. Focus moves from an ancestor of |xwindow_| to Other + // In each case, we will get a FocusOut with a detail of NotifyPointer. + has_pointer_focus_ = focus_in; + break; + case x11::NotifyDetail::Nonlinear: + case x11::NotifyDetail::NonlinearVirtual: + // We get Nonlinear(Virtual) events when + // 1. Focus moves from Other to |xwindow_| + // (FocusIn with NotifyNonlinear) + // 2. Focus moves from Other to a descendant of |xwindow_| + // (FocusIn with NotifyNonlinearVirtual) + // 3. Focus moves from |xwindow_| to Other + // (FocusOut with NotifyNonlinear) + // 4. Focus moves from a descendant of |xwindow_| to Other + // (FocusOut with NotifyNonlinearVirtual) + // |has_pointer_focus_| should be false before and after this event. + has_pointer_focus_ = false; + break; + default: + break; + } + } + + ignore_keyboard_input_ = false; + + AfterActivationStateChanged(); +} + +bool X11Window::IsTargetedBy(const x11::Event& x11_event) const { + return x11_event.window() == xwindow_; +} + +void X11Window::SetTransientWindow(x11::Window window) { + transient_window_ = window; +} + +void X11Window::HandleEvent(const x11::Event& xev) { + if (!IsTargetedBy(xev)) + return; + + // We can lose track of the window's position when the window is reparented. + // When the parent window is moved, we won't get an event, so the window's + // position relative to the root window will get out-of-sync. We can re-sync + // when getting pointer events (EnterNotify, LeaveNotify, ButtonPress, + // ButtonRelease, MotionNotify) which include the pointer location both + // relative to this window and relative to the root window, so we can + // calculate this window's position from that information. + gfx::Point window_point = EventLocationFromXEvent(xev); + gfx::Point root_point = EventSystemLocationFromXEvent(xev); + if (!window_point.IsOrigin() && !root_point.IsOrigin()) { + gfx::Point window_origin = gfx::Point() + (root_point - window_point); + if (bounds_in_pixels_.origin() != window_origin) { + bounds_in_pixels_.set_origin(window_origin); + NotifyBoundsChanged(bounds_in_pixels_); + } + } + + // May want to factor CheckXEventForConsistency(xev); into a common location + // since it is called here. + if (auto* crossing = xev.As()) { + bool focus = crossing->same_screen_focus & CROSSING_FLAG_FOCUS; + OnCrossingEvent(crossing->opcode == x11::CrossingEvent::EnterNotify, focus, + crossing->mode, crossing->detail); + } else if (auto* expose = xev.As()) { + gfx::Rect damage_rect_in_pixels(expose->x, expose->y, expose->width, + expose->height); + OnXWindowDamageEvent(damage_rect_in_pixels); + } else if (auto* focus = xev.As()) { + OnFocusEvent(focus->opcode == x11::FocusEvent::In, focus->mode, + focus->detail); + } else if (auto* configure = xev.As()) { + OnConfigureEvent(*configure); + } else if (auto* crossing = xev.As()) { + TouchFactory* factory = TouchFactory::GetInstance(); + if (factory->ShouldProcessCrossingEvent(*crossing)) { + auto mode = XI2ModeToXMode(crossing->mode); + auto detail = XI2DetailToXDetail(crossing->detail); + switch (crossing->opcode) { + case x11::Input::CrossingEvent::Enter: + OnCrossingEvent(true, crossing->focus, mode, detail); + break; + case x11::Input::CrossingEvent::Leave: + OnCrossingEvent(false, crossing->focus, mode, detail); + break; + case x11::Input::CrossingEvent::FocusIn: + OnFocusEvent(true, mode, detail); + break; + case x11::Input::CrossingEvent::FocusOut: + OnFocusEvent(false, mode, detail); + break; + } + } + } else if (xev.As()) { + OnWindowMapped(); + } else if (xev.As()) { + window_mapped_in_server_ = false; + has_pointer_ = false; + has_pointer_grab_ = false; + has_pointer_focus_ = false; + has_window_focus_ = false; + } else if (auto* client = xev.As()) { + x11::Atom message_type = client->type; + if (message_type == x11::GetAtom("WM_PROTOCOLS")) { + x11::Atom protocol = static_cast(client->data.data32[0]); + if (protocol == x11::GetAtom("WM_DELETE_WINDOW")) { + // We have received a close message from the window manager. + OnXWindowCloseRequested(); + } else if (protocol == x11::GetAtom("_NET_WM_PING")) { + x11::ClientMessageEvent reply_event = *client; + reply_event.window = x_root_window_; + x11::SendEvent(reply_event, x_root_window_, + x11::EventMask::SubstructureNotify | + x11::EventMask::SubstructureRedirect); + } else if (protocol == x11::GetAtom("_NET_WM_SYNC_REQUEST")) { + pending_counter_value_ = + client->data.data32[2] + + (static_cast(client->data.data32[3]) << 32); + pending_counter_value_is_extended_ = client->data.data32[4] != 0; + } + } else { + OnXWindowDragDropEvent(*client); + } + } else if (auto* property = xev.As()) { + x11::Atom changed_atom = property->atom; + if (changed_atom == x11::GetAtom("_NET_WM_STATE")) + OnWMStateUpdated(); + else if (changed_atom == x11::GetAtom("_NET_FRAME_EXTENTS")) + OnFrameExtentsUpdated(); + else if (changed_atom == x11::GetAtom("_NET_WM_DESKTOP")) + OnWorkspaceUpdated(); + } else if (auto* selection = xev.As()) { + OnXWindowSelectionEvent(*selection); + } +} + +void X11Window::UpdateWMUserTime(Event* event) { + if (!IsActive()) + return; + DCHECK(event); + EventType type = event->type(); + if (type == ET_MOUSE_PRESSED || type == ET_KEY_PRESSED || + type == ET_TOUCH_PRESSED) { + uint32_t wm_user_time_ms = + (event->time_stamp() - base::TimeTicks()).InMilliseconds(); + x11::SetProperty(xwindow_, x11::GetAtom("_NET_WM_USER_TIME"), + x11::Atom::CARDINAL, wm_user_time_ms); + } +} + +void X11Window::OnWindowMapped() { + window_mapped_in_server_ = true; + // Some WMs only respect maximize hints after the window has been mapped. + // Check whether we need to re-do a maximization. + if (should_maximize_after_map_) { + Maximize(); + should_maximize_after_map_ = false; + } +} + +void X11Window::OnConfigureEvent(const x11::ConfigureNotifyEvent& configure) { + DCHECK_EQ(xwindow_, configure.window); + DCHECK_EQ(xwindow_, configure.event); + + if (pending_counter_value_) { + DCHECK(!configure_counter_value_); + configure_counter_value_ = pending_counter_value_; + configure_counter_value_is_extended_ = pending_counter_value_is_extended_; + pending_counter_value_is_extended_ = false; + pending_counter_value_ = 0; + } + + // It's possible that the X window may be resized by some other means than + // from within aura (e.g. the X window manager can change the size). Make + // sure the root window size is maintained properly. + int translated_x_in_pixels = configure.x; + int translated_y_in_pixels = configure.y; + if (!configure.send_event && !configure.override_redirect) { + auto future = + connection_->TranslateCoordinates({xwindow_, x_root_window_, 0, 0}); + if (auto coords = future.Sync()) { + translated_x_in_pixels = coords->dst_x; + translated_y_in_pixels = coords->dst_y; + } + } + gfx::Rect new_bounds_px(translated_x_in_pixels, translated_y_in_pixels, + configure.width, configure.height); + const bool size_changed = bounds_in_pixels_.size() != new_bounds_px.size(); + const bool origin_changed = + bounds_in_pixels_.origin() != new_bounds_px.origin(); + previous_bounds_in_pixels_ = bounds_in_pixels_; + bounds_in_pixels_ = new_bounds_px; + + if (size_changed) + DispatchResize(); + else if (origin_changed) + NotifyBoundsChanged(bounds_in_pixels_); +} + +void X11Window::SetWMSpecState(bool enabled, + x11::Atom state1, + x11::Atom state2) { + if (window_mapped_in_client_) { + ui::SetWMSpecState(xwindow_, enabled, state1, state2); + } else { + // The updated state will be set when the window is (re)mapped. + base::flat_set new_window_properties = window_properties_; + for (x11::Atom atom : {state1, state2}) { + if (enabled) + new_window_properties.insert(atom); + else + new_window_properties.erase(atom); + } + UpdateWindowProperties(new_window_properties); + } +} + +void X11Window::OnWMStateUpdated() { + // The EWMH spec requires window managers to remove the _NET_WM_STATE property + // when a window is unmapped. However, Chromium code wants the state to + // persist across a Hide() and Show(). So if the window is currently + // unmapped, leave the state unchanged so it will be restored when the window + // is remapped. + std::vector atom_list; + if (GetArrayProperty(xwindow_, x11::GetAtom("_NET_WM_STATE"), &atom_list) || + window_mapped_in_client_) { + UpdateWindowProperties( + base::flat_set(std::begin(atom_list), std::end(atom_list))); + } +} + +void X11Window::UpdateWindowProperties( + const base::flat_set& new_window_properties) { + was_minimized_ = IsMinimized(); + + window_properties_ = new_window_properties; + + // Ignore requests by the window manager to enter or exit fullscreen (e.g. as + // a result of pressing a window manager accelerator key). Chrome does not + // handle window manager initiated fullscreen. In particular, Chrome needs to + // do preprocessing before the x window's fullscreen state is toggled. + + is_always_on_top_ = HasWMSpecProperty(window_properties_, + x11::GetAtom("_NET_WM_STATE_ABOVE")); + OnXWindowStateChanged(); + ResetWindowRegion(); +} + +void X11Window::OnFrameExtentsUpdated() { + std::vector insets; + if (GetArrayProperty(xwindow_, x11::GetAtom("_NET_FRAME_EXTENTS"), &insets) && + insets.size() == 4) { + // |insets| are returned in the order: [left, right, top, bottom]. + native_window_frame_borders_in_pixels_ = + gfx::Insets(insets[2], insets[0], insets[3], insets[1]); + } else { + native_window_frame_borders_in_pixels_ = gfx::Insets(); + } +} + +// Removes |delayed_resize_task_| from the task queue (if it's in the queue) and +// adds it back at the end of the queue. +void X11Window::DispatchResize() { + if (update_counter_ == x11::Sync::Counter{} || + configure_counter_value_ == 0) { + // WM doesn't support _NET_WM_SYNC_REQUEST. Or we are too slow, so + // _NET_WM_SYNC_REQUEST is disabled by the compositor. + delayed_resize_task_.Reset(base::BindOnce( + &X11Window::DelayedResize, base::Unretained(this), bounds_in_pixels_)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, delayed_resize_task_.callback()); + return; + } + + if (configure_counter_value_is_extended_) { + current_counter_value_ = configure_counter_value_; + configure_counter_value_ = 0; + // Make sure the counter is even number. + if ((current_counter_value_ % 2) == 1) + ++current_counter_value_; + } + + // If _NET_WM_SYNC_REQUEST is used to synchronize with compositor during + // resizing, the compositor will not resize the window, until last resize is + // handled, so we don't need accumulate resize events. + DelayedResize(bounds_in_pixels_); +} + +void X11Window::DelayedResize(const gfx::Rect& bounds_in_pixels) { + if (configure_counter_value_is_extended_ && + (current_counter_value_ % 2) == 0) { + // Increase the |extended_update_counter_|, so the compositor will know we + // are not frozen and re-enable _NET_WM_SYNC_REQUEST, if it was disabled. + // Increase the |extended_update_counter_| to an odd number will not trigger + // a new resize. + SyncSetCounter(connection_, extended_update_counter_, + ++current_counter_value_); + } + + CancelResize(); + NotifyBoundsChanged(bounds_in_pixels); + + // No more member accesses here: bounds change propagation may have deleted + // |this| (e.g. when a chrome window is snapped into a tab strip. Further + // details at crbug.com/1068755). +} + +void X11Window::CancelResize() { + delayed_resize_task_.Cancel(); +} + +void X11Window::UnconfineCursor() { + if (!has_pointer_barriers_) + return; + + for (auto pointer_barrier : pointer_barriers_) + connection_->xfixes().DeletePointerBarrier({pointer_barrier}); + + pointer_barriers_.fill({}); + + has_pointer_barriers_ = false; +} + +void X11Window::UpdateWindowRegion( + std::unique_ptr> region) { + auto set_shape = [&](const std::vector& rectangles) { + connection_->shape().Rectangles(x11::Shape::RectanglesRequest{ + .operation = x11::Shape::So::Set, + .destination_kind = x11::Shape::Sk::Bounding, + .ordering = x11::ClipOrdering::YXBanded, + .destination_window = xwindow_, + .rectangles = rectangles, + }); + }; + + // If a custom window shape was supplied then apply it. + if (custom_window_shape_) { + set_shape(*window_shape_); + return; + } + + window_shape_ = std::move(region); + if (window_shape_) { + set_shape(*window_shape_); + return; + } + + // If we didn't set the shape for any reason, reset the shaping information. + // How this is done depends on the border style, due to quirks and bugs in + // various window managers. + if (use_native_frame_) { + // If the window has system borders, the mask must be set to null (not a + // rectangle), because several window managers (eg, KDE, XFCE, XMonad) will + // not put borders on a window with a custom shape. + connection_->shape().Mask(x11::Shape::MaskRequest{ + .operation = x11::Shape::So::Set, + .destination_kind = x11::Shape::Sk::Bounding, + .destination_window = xwindow_, + .source_bitmap = x11::Pixmap::None, + }); + } else { + // Conversely, if the window does not have system borders, the mask must be + // manually set to a rectangle that covers the whole window (not null). This + // is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null + // shape causes the hint to disable system borders to be ignored (resulting + // in a double border). + x11::Rectangle r{0, 0, bounds_in_pixels_.width(), + bounds_in_pixels_.height()}; + set_shape({r}); + } +} + +void X11Window::NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px) { + ResetWindowRegion(); + OnXWindowBoundsChanged(new_bounds_in_px); +} + +bool X11Window::InitializeAsStatusIcon() { + std::string atom_name = "_NET_SYSTEM_TRAY_S" + + base::NumberToString(connection_->DefaultScreenId()); + auto reply = connection_->GetSelectionOwner({x11::GetAtom(atom_name)}).Sync(); + if (!reply || reply->owner == x11::Window::None) + return false; + auto manager = reply->owner; + + SetArrayProperty( + xwindow_, x11::GetAtom("_XEMBED_INFO"), x11::Atom::CARDINAL, + std::vector{kXembedInfoProtocolVersion, kXembedInfoFlags}); + + x11::ChangeWindowAttributesRequest req{xwindow_}; + if (visual_has_alpha_) { + req.background_pixel = 0; + } else { + x11::SetProperty(xwindow_, x11::GetAtom("CHROMIUM_COMPOSITE_WINDOW"), + x11::Atom::CARDINAL, static_cast(1)); + req.background_pixmap = + static_cast(x11::BackPixmap::ParentRelative); + } + connection_->ChangeWindowAttributes(req); + + auto future = SendClientMessage( + manager, manager, x11::GetAtom("_NET_SYSTEM_TRAY_OPCODE"), + {static_cast(X11EventSource::GetInstance()->GetTimestamp()), + kSystemTrayRequestDock, static_cast(xwindow_), 0, 0}, + x11::EventMask::NoEvent); + return !future.Sync().error; +} + } // namespace ui diff --git a/chromium/ui/platform_window/x11/x11_window.h b/chromium/ui/platform_window/x11/x11_window.h index 4693ac5f148..3a78032d846 100644 --- a/chromium/ui/platform_window/x11/x11_window.h +++ b/chromium/ui/platform_window/x11/x11_window.h @@ -5,12 +5,22 @@ #ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_ #define UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_ +#include +#include +#include +#include + +#include "base/cancelable_callback.h" #include "base/macros.h" +#include "ui/base/x/x11_desktop_window_move_client.h" #include "ui/base/x/x11_drag_drop_client.h" #include "ui/base/x/x11_move_loop_delegate.h" -#include "ui/base/x/x11_window.h" #include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/x/event.h" +#include "ui/gfx/x/sync.h" +#include "ui/gfx/x/xfixes.h" +#include "ui/gfx/x/xproto.h" #include "ui/platform_window/extensions/workspace_extension.h" #include "ui/platform_window/extensions/x11_extension.h" #include "ui/platform_window/platform_window.h" @@ -20,55 +30,44 @@ #include "ui/platform_window/wm/wm_move_resize_handler.h" #include "ui/platform_window/x11/x11_window_export.h" +class SkPath; + namespace ui { class PlatformWindowDelegate; class X11ExtensionDelegate; -class X11DesktopWindowMoveClient; class X11MoveLoop; class LocatedEvent; class WorkspaceExtensionDelegate; -// Delegate interface used to communicate the X11PlatformWindow API client about -// x11::Events of interest. -class X11_WINDOW_EXPORT XEventDelegate { - public: - virtual ~XEventDelegate() = default; - - // TODO(crbug.com/990756): We need to implement/reuse ozone interface for - // these. - virtual void OnXWindowSelectionEvent( - const x11::SelectionNotifyEvent& xev) = 0; - virtual void OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev) = 0; -}; - // PlatformWindow implementation for X11. -class X11_WINDOW_EXPORT X11Window : public PlatformWindow, - public WmMoveResizeHandler, - public XWindow, - public PlatformEventDispatcher, - public x11::EventObserver, - public WorkspaceExtension, - public X11Extension, - public WmDragHandler, - public XDragDropClient::Delegate, - public X11MoveLoopDelegate, - public WmMoveLoopHandler { +class X11_WINDOW_EXPORT X11Window + : public PlatformWindow, + public WmMoveResizeHandler, + public PlatformEventDispatcher, + public x11::EventObserver, + public WorkspaceExtension, + public X11Extension, + public WmDragHandler, + public XDragDropClient::Delegate, + public X11MoveLoopDelegate, + public WmMoveLoopHandler, + public X11DesktopWindowMoveClient::Delegate { public: explicit X11Window(PlatformWindowDelegate* platform_window_delegate); ~X11Window() override; virtual void Initialize(PlatformWindowInitProperties properties); - void SetXEventDelegate(XEventDelegate* delegate); - // X11WindowManager calls this. // XWindow override: - void OnXWindowLostCapture() override; + void OnXWindowLostCapture(); void OnMouseEnter(); gfx::AcceleratedWidget GetWidget() const; + gfx::Rect GetOuterBounds() const; + void SetTransientWindow(x11::Window window); // PlatformWindow: void Show(bool inactive) override; @@ -78,7 +77,7 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, void PrepareForShutdown() override; void SetBounds(const gfx::Rect& bounds) override; gfx::Rect GetBounds() const override; - void SetTitle(const base::string16& title) override; + void SetTitle(const std::u16string& title) override; void SetCapture() override; void ReleaseCapture() override; bool HasCapture() const override; @@ -136,26 +135,25 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, return platform_window_delegate_; } - bool is_shutting_down() const { return is_shutting_down_; } - - // XWindow: - void OnXWindowCreated() override; - - // XWindow: - void OnXWindowStateChanged() override; - void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override; - void OnXWindowBoundsChanged(const gfx::Rect& size) override; - void OnXWindowCloseRequested() override; - void OnXWindowIsActiveChanged(bool active) override; - void OnXWindowWorkspaceChanged() override; - void OnXWindowLostPointerGrab() override; - void OnXWindowSelectionEvent(const x11::SelectionNotifyEvent& xev) override; - void OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev) override; - base::Optional GetMinimumSizeForXWindow() override; - base::Optional GetMaximumSizeForXWindow() override; - SkPath GetWindowMaskForXWindow() override; + void OnXWindowStateChanged(); + void OnXWindowDamageEvent(const gfx::Rect& damage_rect); + void OnXWindowBoundsChanged(const gfx::Rect& size); + void OnXWindowCloseRequested(); + void OnXWindowIsActiveChanged(bool active); + void OnXWindowWorkspaceChanged(); + void OnXWindowLostPointerGrab(); + void OnXWindowSelectionEvent(const x11::SelectionNotifyEvent& xev); + void OnXWindowDragDropEvent(const x11::ClientMessageEvent& xev); + base::Optional GetMinimumSizeForXWindow(); + base::Optional GetMaximumSizeForXWindow(); + SkPath GetWindowMaskForXWindow(); private: + FRIEND_TEST_ALL_PREFIXES(X11WindowTest, Shape); + FRIEND_TEST_ALL_PREFIXES(X11WindowTest, WindowManagerTogglesFullscreen); + FRIEND_TEST_ALL_PREFIXES(X11WindowTest, + ToggleMinimizePropogateToPlatformWindowDelegate); + // PlatformEventDispatcher: bool CanDispatchEvent(const PlatformEvent& event) override; uint32_t DispatchEvent(const PlatformEvent& event) override; @@ -196,6 +194,11 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, void OnMouseReleased() override; void OnMoveLoopEnded() override; + // X11DesktopWindowMoveClient::Delegate: + void SetBoundsOnMove(const gfx::Rect& requested_bounds) override; + scoped_refptr GetLastCursor() override; + gfx::Size GetSize() override; + void QuitDragLoop(); // Handles |xevent| as a Atk Key Event @@ -213,13 +216,99 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, const gfx::Rect& current_window_bounds, ui::LocatedEvent* located_event); + // Creates the X window with the given properties. + // 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 CloseXWindow(); + void Map(bool inactive = false); + void SetFullscreen(bool fullscreen); + bool IsActive() const; + bool IsTargetedBy(const x11::Event& xev) const; + void HandleEvent(const x11::Event& xev); + + bool IsMinimized() const; + bool IsMaximized() const; + bool IsFullscreen() const; + + void SetFlashFrameHint(bool flash_frame); + void UpdateMinAndMaxSize(); + void DispatchResize(); + void CancelResize(); + + // Resets the window region for the current window bounds if necessary. + void ResetWindowRegion(); + + x11::Window window() const { return xwindow_; } + x11::Window root_window() const { return x_root_window_; } + std::vector* shape() const { return window_shape_.get(); } + + // Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active. + void UpdateWMUserTime(ui::Event* event); + + // Called on an XFocusInEvent, XFocusOutEvent, XIFocusInEvent, or an + // XIFocusOutEvent. + void OnFocusEvent(bool focus_in, + x11::NotifyMode mode, + x11::NotifyDetail detail); + + // Called on an XEnterWindowEvent, XLeaveWindowEvent, XIEnterEvent, or an + // XILeaveEvent. + void OnCrossingEvent(bool enter, + bool focus_in_window_or_ancestor, + x11::NotifyMode mode, + x11::NotifyDetail detail); + + // Called when |xwindow_|'s _NET_WM_STATE property is updated. + void OnWMStateUpdated(); + + // Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated. + void OnFrameExtentsUpdated(); + + void OnConfigureEvent(const x11::ConfigureNotifyEvent& event); + + void OnWorkspaceUpdated(); + + void OnWindowMapped(); + + // Record the activation state. + void BeforeActivationStateChanged(); + + // Handle the state change since BeforeActivationStateChanged(). + void AfterActivationStateChanged(); + + void DelayedResize(const gfx::Rect& bounds_in_pixels); + + // If mapped, sends a message to the window manager to enable or disable the + // states |state1| and |state2|. Otherwise, the states will be enabled or + // disabled on the next map. It's the caller's responsibility to make sure + // atoms are set and unset in the appropriate pairs. For example, if a caller + // sets (_NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ), it would + // be invalid to unset the maximized state by making two calls like + // (_NET_WM_STATE_MAXIMIZED_VERT, x11::None), (_NET_WM_STATE_MAXIMIZED_HORZ, + // x11::None). + void SetWMSpecState(bool enabled, x11::Atom state1, x11::Atom state2); + + // Updates |window_properties_| with |new_window_properties|. + void UpdateWindowProperties( + const base::flat_set& new_window_properties); + + void UnconfineCursor(); + + void UpdateWindowRegion(std::unique_ptr> region); + + void NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px); + + // Initializes as a status icon window. + bool InitializeAsStatusIcon(); + // Stores current state of this window. PlatformWindowState state_ = PlatformWindowState::kUnknown; PlatformWindowDelegate* const platform_window_delegate_; - XEventDelegate* x_event_delegate_ = nullptr; - WorkspaceExtensionDelegate* workspace_extension_delegate_ = nullptr; X11ExtensionDelegate* x11_extension_delegate_ = nullptr; @@ -251,6 +340,143 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow, // Events that we have selected on the source window of the incoming drag. std::unique_ptr source_window_events_; + // The display and the native X window hosting the root window. + x11::Connection* const connection_; + x11::Window xwindow_ = x11::Window::None; + x11::Window x_root_window_ = x11::Window::None; + + // Any native, modal dialog hanging from this window. + x11::Window transient_window_ = x11::Window::None; + + // Events selected on |xwindow_|. + std::unique_ptr xwindow_events_; + + // The window manager state bits. + base::flat_set window_properties_; + + // Is this window able to receive focus? + bool activatable_ = true; + + // Was this window initialized with the override_redirect window attribute? + bool override_redirect_ = false; + + std::u16string window_title_; + + // Whether the window is visible with respect to Aura. + bool window_mapped_in_client_ = false; + + // Whether the window is mapped with respect to the X server. + bool window_mapped_in_server_ = false; + + // The bounds of |xwindow_|. + gfx::Rect bounds_in_pixels_; + + x11::VisualId visual_id_{}; + + // Whether we used an ARGB visual for our window. + bool visual_has_alpha_ = false; + + // The workspace containing |xwindow_|. This will be base::nullopt when + // _NET_WM_DESKTOP is unset. + base::Optional workspace_; + + // True if the window should stay on top of most other windows. + bool is_always_on_top_ = false; + + // Does |xwindow_| have the pointer grab (XI2 or normal)? + bool has_pointer_grab_ = false; + + // The focus-tracking state variables are as described in + // gtk/docs/focus_tracking.txt + // + // |xwindow_| is active iff: + // (|has_window_focus_| || |has_pointer_focus_|) && + // !|ignore_keyboard_input_| + + // Is the pointer in |xwindow_| or one of its children? + bool has_pointer_ = false; + + // Is |xwindow_| or one of its children focused? + bool has_window_focus_ = false; + + // (An ancestor window or the PointerRoot is focused) && |has_pointer_|. + // |has_pointer_focus_| == true is the odd case where we will receive keyboard + // input when |has_window_focus_| == false. |has_window_focus_| and + // |has_pointer_focus_| are mutually exclusive. + bool has_pointer_focus_ = false; + + // X11 does not support defocusing windows; you can only focus a different + // window. If we would like to be defocused, we just ignore keyboard input we + // no longer care about. + bool ignore_keyboard_input_ = false; + + // Used for tracking activation state in {Before|After}ActivationStateChanged. + bool was_active_ = false; + bool had_pointer_ = false; + bool had_pointer_grab_ = false; + bool had_window_focus_ = false; + + bool was_minimized_ = false; + + // Used for synchronizing between |xwindow_| and desktop compositor during + // resizing. + x11::Sync::Counter update_counter_{}; + x11::Sync::Counter extended_update_counter_{}; + + // Whenever the bounds are set, we keep the previous set of bounds around so + // we can have a better chance of getting the real + // |restored_bounds_in_pixels_|. Window managers tend to send a Configure + // message with the maximized bounds, and then set the window maximized + // property. (We don't rely on this for when we request that the window be + // maximized, only when we detect that some other process has requested that + // we become the maximized window.) + gfx::Rect previous_bounds_in_pixels_; + + // True if a Maximize() call should be done after mapping the window. + bool should_maximize_after_map_ = false; + + // Whether we currently are flashing our frame. This feature is implemented + // by setting the urgency hint with the window manager, which can draw + // attention to the window or completely ignore the hint. We stop flashing + // the frame when |xwindow_| gains focus or handles a mouse button event. + bool urgency_hint_set_ = false; + + // |xwindow_|'s minimum size. + gfx::Size min_size_in_pixels_; + + // |xwindow_|'s maximum size. + gfx::Size max_size_in_pixels_; + + // The window shape if the window is non-rectangular. + std::unique_ptr> window_shape_; + + // Whether |window_shape_| was set via SetShape(). + bool custom_window_shape_ = false; + + // True if the window has title-bar / borders provided by the window manager. + bool use_native_frame_ = false; + + // The size of the window manager provided borders (if any). + gfx::Insets native_window_frame_borders_in_pixels_; + + // Used for synchronizing between |xwindow_| between desktop compositor during + // resizing. + int64_t pending_counter_value_ = 0; + int64_t configure_counter_value_ = 0; + int64_t current_counter_value_ = 0; + bool pending_counter_value_is_extended_ = false; + bool configure_counter_value_is_extended_ = false; + + base::CancelableOnceClosure delayed_resize_task_; + + // Keep track of barriers to confine cursor. + bool has_pointer_barriers_ = false; + std::array pointer_barriers_; + + scoped_refptr last_cursor_; + + base::CancelableOnceCallback on_cursor_loaded_; + base::WeakPtrFactory weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(X11Window); diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block.png new file mode 100644 index 00000000000..79e46a157ae Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block_big.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block_big.png new file mode 100644 index 00000000000..92741752c2c Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/sb_horizontal_double_arrow_block_big.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block.png new file mode 100644 index 00000000000..c8f2c2a8ffa Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block_big.png b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block_big.png new file mode 100644 index 00000000000..dca563264a9 Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/sb_vertical_double_arrow_block_big.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block.png b/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block.png new file mode 100644 index 00000000000..a4d31a2b68f Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block_big.png b/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block_big.png new file mode 100644 index 00000000000..5730309cb01 Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/top_left_corner_block_big.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block.png b/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block.png new file mode 100644 index 00000000000..efc7eba4304 Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block.png differ diff --git a/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block_big.png b/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block_big.png new file mode 100644 index 00000000000..9a6e2caa534 Binary files /dev/null and b/chromium/ui/resources/default_100_percent/common/pointers/top_right_corner_block_big.png differ diff --git a/chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow_block.png b/chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow_block.png new file mode 100644 index 00000000000..7f4eeee7d63 Binary files /dev/null and b/chromium/ui/resources/default_200_percent/common/pointers/sb_horizontal_double_arrow_block.png differ diff --git a/chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow_block.png b/chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow_block.png new file mode 100644 index 00000000000..2e42175ae20 Binary files /dev/null and b/chromium/ui/resources/default_200_percent/common/pointers/sb_vertical_double_arrow_block.png differ diff --git a/chromium/ui/resources/default_200_percent/common/pointers/top_left_corner_block.png b/chromium/ui/resources/default_200_percent/common/pointers/top_left_corner_block.png new file mode 100644 index 00000000000..ec398af9393 Binary files /dev/null and b/chromium/ui/resources/default_200_percent/common/pointers/top_left_corner_block.png differ diff --git a/chromium/ui/resources/default_200_percent/common/pointers/top_right_corner_block.png b/chromium/ui/resources/default_200_percent/common/pointers/top_right_corner_block.png new file mode 100644 index 00000000000..710289fc0d5 Binary files /dev/null and b/chromium/ui/resources/default_200_percent/common/pointers/top_right_corner_block.png differ diff --git a/chromium/ui/resources/ui_resources.grd b/chromium/ui/resources/ui_resources.grd index 7c4d37b3b60..38731743307 100644 --- a/chromium/ui/resources/ui_resources.grd +++ b/chromium/ui/resources/ui_resources.grd @@ -24,6 +24,7 @@ + @@ -32,10 +33,13 @@ + + + @@ -53,6 +57,7 @@ + @@ -61,10 +66,13 @@ + + + diff --git a/chromium/ui/shell_dialogs/execute_select_file_win.cc b/chromium/ui/shell_dialogs/execute_select_file_win.cc index 7b5a8506a9c..063d4c7c96c 100644 --- a/chromium/ui/shell_dialogs/execute_select_file_win.cc +++ b/chromium/ui/shell_dialogs/execute_select_file_win.cc @@ -101,8 +101,8 @@ bool SetOptions(IFileDialog* file_dialog, DWORD dialog_options) { // Configures a |file_dialog| object given the specified parameters. bool ConfigureDialog(IFileDialog* file_dialog, - const base::string16& title, - const base::string16& ok_button_label, + const std::u16string& title, + const std::u16string& ok_button_label, const base::FilePath& default_path, const std::vector& filter, int filter_index, @@ -134,7 +134,7 @@ bool ConfigureDialog(IFileDialog* file_dialog, // and extension of the user selected file name. |def_ext| is the default // extension to give to the file if the user did not enter an extension. bool RunSaveFileDialog(HWND owner, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const std::vector& filter, DWORD dialog_options, @@ -148,7 +148,7 @@ bool RunSaveFileDialog(HWND owner, return false; } - if (!ConfigureDialog(file_save_dialog.Get(), title, base::string16(), + if (!ConfigureDialog(file_save_dialog.Get(), title, std::u16string(), default_path, filter, *filter_index, dialog_options)) { return false; } @@ -183,8 +183,8 @@ bool RunSaveFileDialog(HWND owner, // Runs an Open file dialog box, with similar semantics for input parameters as // RunSaveFileDialog. bool RunOpenFileDialog(HWND owner, - const base::string16& title, - const base::string16& ok_button_label, + const std::u16string& title, + const std::u16string& ok_button_label, const base::FilePath& default_path, const std::vector& filter, DWORD dialog_options, @@ -255,12 +255,12 @@ bool RunOpenFileDialog(HWND owner, // thread. bool ExecuteSelectFolder(HWND owner, SelectFileDialog::Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, std::vector* paths) { DCHECK(paths); - base::string16 new_title = title; + std::u16string new_title = title; if (new_title.empty() && type == SelectFileDialog::SELECT_UPLOAD_FOLDER) { // If it's for uploading don't use default dialog title to // make sure we clearly tell it's for uploading. @@ -268,7 +268,7 @@ bool ExecuteSelectFolder(HWND owner, l10n_util::GetStringUTF16(IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE); } - base::string16 ok_button_label; + std::u16string ok_button_label; if (type == SelectFileDialog::SELECT_UPLOAD_FOLDER) { ok_button_label = l10n_util::GetStringUTF16( IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON); @@ -284,19 +284,19 @@ bool ExecuteSelectFolder(HWND owner, } bool ExecuteSelectSingleFile(HWND owner, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const std::vector& filter, int* filter_index, std::vector* paths) { // Note: The title is not passed down for historical reasons. // TODO(pmonette): Figure out if it's a worthwhile improvement. - return RunOpenFileDialog(owner, base::string16(), base::string16(), + return RunOpenFileDialog(owner, std::u16string(), std::u16string(), default_path, filter, 0, filter_index, paths); } bool ExecuteSelectMultipleFile(HWND owner, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const std::vector& filter, int* filter_index, @@ -305,7 +305,7 @@ bool ExecuteSelectMultipleFile(HWND owner, // Note: The title is not passed down for historical reasons. // TODO(pmonette): Figure out if it's a worthwhile improvement. - return RunOpenFileDialog(owner, base::string16(), base::string16(), + return RunOpenFileDialog(owner, std::u16string(), std::u16string(), default_path, filter, dialog_options, filter_index, paths); } @@ -325,7 +325,7 @@ bool ExecuteSaveFile(HWND owner, // Note: The title is not passed down for historical reasons. // TODO(pmonette): Figure out if it's a worthwhile improvement. - return RunSaveFileDialog(owner, base::string16(), default_path, filter, + return RunSaveFileDialog(owner, std::u16string(), default_path, filter, dialog_options, def_ext, filter_index, path); } @@ -373,7 +373,7 @@ std::wstring AppendExtensionIfNeeded(const std::wstring& filename, void ExecuteSelectFile( SelectFileDialog::Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const std::vector& filter, int file_type_index, diff --git a/chromium/ui/shell_dialogs/execute_select_file_win.h b/chromium/ui/shell_dialogs/execute_select_file_win.h index 74735f6259e..dc808af3953 100644 --- a/chromium/ui/shell_dialogs/execute_select_file_win.h +++ b/chromium/ui/shell_dialogs/execute_select_file_win.h @@ -5,11 +5,11 @@ #ifndef UI_SHELL_DIALOGS_EXECUTE_SELECT_FILE_WIN_H_ #define UI_SHELL_DIALOGS_EXECUTE_SELECT_FILE_WIN_H_ +#include #include #include #include "base/callback_forward.h" -#include "base/strings/string16.h" #include "base/win/windows_types.h" #include "ui/shell_dialogs/select_file_dialog.h" #include "ui/shell_dialogs/shell_dialogs_export.h" @@ -29,11 +29,11 @@ SHELL_DIALOGS_EXPORT std::wstring AppendExtensionIfNeeded( // Describes a filter for a file dialog. struct FileFilterSpec { // A human readable description of this filter. E.g. "HTML Files." - base::string16 description; + std::u16string description; // The different extensions that map to this spec. This is a semicolon- // separated list of extensions that contains a wildcard and the separator. // E.g. "*.html;*.htm" - base::string16 extension_spec; + std::u16string extension_spec; }; using OnSelectFileExecutedCallback = @@ -45,7 +45,7 @@ using OnSelectFileExecutedCallback = SHELL_DIALOGS_EXPORT void ExecuteSelectFile( SelectFileDialog::Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const std::vector& filter, int file_type_index, diff --git a/chromium/ui/shell_dialogs/fake_select_file_dialog.cc b/chromium/ui/shell_dialogs/fake_select_file_dialog.cc index d70a3e090d2..0d0a5176659 100644 --- a/chromium/ui/shell_dialogs/fake_select_file_dialog.cc +++ b/chromium/ui/shell_dialogs/fake_select_file_dialog.cc @@ -54,7 +54,7 @@ bool FakeSelectFileDialog::IsRunning(gfx::NativeWindow owning_window) const { void FakeSelectFileDialog::SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/fake_select_file_dialog.h b/chromium/ui/shell_dialogs/fake_select_file_dialog.h index 184625436cc..428f1f926f8 100644 --- a/chromium/ui/shell_dialogs/fake_select_file_dialog.h +++ b/chromium/ui/shell_dialogs/fake_select_file_dialog.h @@ -5,10 +5,11 @@ #ifndef UI_SHELL_DIALOGS_FAKE_SELECT_FILE_DIALOG_H_ #define UI_SHELL_DIALOGS_FAKE_SELECT_FILE_DIALOG_H_ +#include + #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "ui/shell_dialogs/select_file_dialog.h" #include "ui/shell_dialogs/select_file_dialog_factory.h" @@ -68,7 +69,7 @@ class FakeSelectFileDialog : public SelectFileDialog { // SelectFileDialog. void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -80,7 +81,7 @@ class FakeSelectFileDialog : public SelectFileDialog { void ListenerDestroyed() override {} // Returns the file title provided to the dialog. - const base::string16& title() const { return title_; } + const std::u16string& title() const { return title_; } // Returns the file types provided to the dialog. const FileTypeInfo& file_types() const { return file_types_; } // Returns the default file extension provided to the dialog. @@ -99,7 +100,7 @@ class FakeSelectFileDialog : public SelectFileDialog { ~FakeSelectFileDialog() override; base::RepeatingClosure opened_; - base::string16 title_; + std::u16string title_; FileTypeInfo file_types_; std::string default_extension_; void* params_; diff --git a/chromium/ui/shell_dialogs/select_file_dialog.cc b/chromium/ui/shell_dialogs/select_file_dialog.cc index 6e760139708..52e9ec21b13 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog.cc +++ b/chromium/ui/shell_dialogs/select_file_dialog.cc @@ -96,7 +96,7 @@ base::FilePath SelectFileDialog::GetShortenedFilePath( void SelectFileDialog::SelectFile( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog.h b/chromium/ui/shell_dialogs/select_file_dialog.h index 0bcc440b21c..a367ba2c004 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog.h +++ b/chromium/ui/shell_dialogs/select_file_dialog.h @@ -13,7 +13,6 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/strings/string16.h" #include "ui/gfx/native_widget_types.h" #include "ui/shell_dialogs/base_shell_dialog.h" #include "ui/shell_dialogs/shell_dialogs_export.h" @@ -132,7 +131,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog // Overrides the system descriptions of the specified extensions. Entries // correspond to |extensions|; if left blank the system descriptions will // be used. - std::vector extension_description_overrides; + std::vector extension_description_overrides; // Specifies whether there will be a filter added for all files (i.e. *.*). bool include_all_files = false; @@ -195,7 +194,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog // NOTE: only one instance of any shell dialog can be shown per owning_window // at a time (for obvious reasons). void SelectFile(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -217,7 +216,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog // AllowFileSelectionDialogs-Policy. virtual void SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.cc b/chromium/ui/shell_dialogs/select_file_dialog_android.cc index 66500a99be7..2388447d65d 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_android.cc +++ b/chromium/ui/shell_dialogs/select_file_dialog_android.cc @@ -112,7 +112,7 @@ void SelectFileDialogImpl::ListenerDestroyed() { void SelectFileDialogImpl::SelectFileImpl( SelectFileDialog::Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const SelectFileDialog::FileTypeInfo* file_types, int file_type_index, @@ -123,9 +123,9 @@ void SelectFileDialogImpl::SelectFileImpl( // The first element in the pair is a list of accepted types, the second // indicates whether the device's capture capabilities should be used. - typedef std::pair, bool> AcceptTypes; - AcceptTypes accept_types = std::make_pair(std::vector(), - false); + typedef std::pair, bool> AcceptTypes; + AcceptTypes accept_types = + std::make_pair(std::vector(), false); if (params) accept_types = *(reinterpret_cast(params)); diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.h b/chromium/ui/shell_dialogs/select_file_dialog_android.h index 719ea966689..bb9e25b0ee6 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_android.h +++ b/chromium/ui/shell_dialogs/select_file_dialog_android.h @@ -47,7 +47,7 @@ class SelectFileDialogImpl : public SelectFileDialog { // params is expected to be a vector with accept_types first and // the capture value as the last element of the vector. void SelectFileImpl(SelectFileDialog::Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const SelectFileDialog::FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc b/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc index f842a551d26..a3790f50820 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc +++ b/chromium/ui/shell_dialogs/select_file_dialog_lacros.cc @@ -102,7 +102,7 @@ bool SelectFileDialogLacros::IsRunning(gfx::NativeWindow owning_window) const { void SelectFileDialogLacros::SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_lacros.h b/chromium/ui/shell_dialogs/select_file_dialog_lacros.h index 9527c314b8f..a2c633e9b04 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_lacros.h +++ b/chromium/ui/shell_dialogs/select_file_dialog_lacros.h @@ -39,7 +39,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialogLacros : public SelectFileDialog { // SelectFileDialog: void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac.h b/chromium/ui/shell_dialogs/select_file_dialog_mac.h index a31753e2219..acc71b65d2c 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_mac.h +++ b/chromium/ui/shell_dialogs/select_file_dialog_mac.h @@ -39,7 +39,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialogImpl : public ui::SelectFileDialog { // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac.mm b/chromium/ui/shell_dialogs/select_file_dialog_mac.mm index 2fcf6f46aa8..9855d3c1e3d 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_mac.mm +++ b/chromium/ui/shell_dialogs/select_file_dialog_mac.mm @@ -69,7 +69,7 @@ void SelectFileDialogImpl::FileWasSelected( void SelectFileDialogImpl::SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm b/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm index 8531ce767d2..224ac8d37aa 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm +++ b/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm @@ -25,8 +25,8 @@ namespace { const int kFileTypePopupTag = 1234; // Returns a vector containing extension descriptions for a given popup. -std::vector GetExtensionDescriptionList(NSPopUpButton* popup) { - std::vector extension_descriptions; +std::vector GetExtensionDescriptionList(NSPopUpButton* popup) { + std::vector extension_descriptions; for (NSString* description in [popup itemTitles]) extension_descriptions.push_back(base::SysNSStringToUTF16(description)); return extension_descriptions; @@ -53,7 +53,7 @@ std::vector GetVectorFromArray(const T (&data)[N]) { // SelectFileDialogImpl::SelectFileImpl. struct FileDialogArguments { ui::SelectFileDialog::Type type; - base::string16 title; + std::u16string title; base::FilePath default_path; ui::SelectFileDialog::FileTypeInfo* file_types; int file_type_index; @@ -66,7 +66,7 @@ struct FileDialogArguments { // appropriate default values. FileDialogArguments GetDefaultArguments() { return {ui::SelectFileDialog::SELECT_SAVEAS_FILE, - base::ASCIIToUTF16(""), + u"", base::FilePath(), nullptr, 0, @@ -131,8 +131,7 @@ class SelectFileDialogMacTest : public testing::Test, // popup item changes the allowed file types. TEST_F(SelectFileDialogMacTest, ExtensionPopup) { const std::string extensions_arr[][2] = {{"html", "htm"}, {"jpeg", "jpg"}}; - const base::string16 extension_descriptions_arr[] = { - base::ASCIIToUTF16("Webpage"), base::ASCIIToUTF16("Image")}; + const std::u16string extension_descriptions_arr[] = {u"Webpage", u"Image"}; SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back( @@ -140,7 +139,7 @@ TEST_F(SelectFileDialogMacTest, ExtensionPopup) { file_type_info.extensions.push_back( GetVectorFromArray(extensions_arr[1])); file_type_info.extension_description_overrides = - GetVectorFromArray(extension_descriptions_arr); + GetVectorFromArray(extension_descriptions_arr); file_type_info.include_all_files = false; FileDialogArguments args(GetDefaultArguments()); @@ -153,7 +152,7 @@ TEST_F(SelectFileDialogMacTest, ExtensionPopup) { EXPECT_TRUE(popup); // Check that the dropdown list created has the correct description. - const std::vector extension_descriptions = + const std::vector extension_descriptions = GetExtensionDescriptionList(popup); EXPECT_EQ(file_type_info.extension_description_overrides, extension_descriptions); @@ -185,8 +184,7 @@ TEST_F(SelectFileDialogMacTest, ExtensionPopup) { // Verify file_type_info.include_all_files argument is respected. TEST_F(SelectFileDialogMacTest, IncludeAllFiles) { const std::string extensions_arr[][2] = {{"html", "htm"}, {"jpeg", "jpg"}}; - const base::string16 extension_descriptions_arr[] = { - base::ASCIIToUTF16("Webpage"), base::ASCIIToUTF16("Image")}; + const std::u16string extension_descriptions_arr[] = {u"Webpage", u"Image"}; SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back( @@ -194,7 +192,7 @@ TEST_F(SelectFileDialogMacTest, IncludeAllFiles) { file_type_info.extensions.push_back( GetVectorFromArray(extensions_arr[1])); file_type_info.extension_description_overrides = - GetVectorFromArray(extension_descriptions_arr); + GetVectorFromArray(extension_descriptions_arr); file_type_info.include_all_files = true; FileDialogArguments args(GetDefaultArguments()); @@ -207,12 +205,12 @@ TEST_F(SelectFileDialogMacTest, IncludeAllFiles) { EXPECT_TRUE(popup); // Check that the dropdown list created has the correct description. - const std::vector extension_descriptions = + const std::vector extension_descriptions = GetExtensionDescriptionList(popup); EXPECT_EQ(3lu, extension_descriptions.size()); - EXPECT_EQ(base::ASCIIToUTF16("Webpage"), extension_descriptions[0]); - EXPECT_EQ(base::ASCIIToUTF16("Image"), extension_descriptions[1]); - EXPECT_EQ(base::ASCIIToUTF16("All Files"), extension_descriptions[2]); + EXPECT_EQ(u"Webpage", extension_descriptions[0]); + EXPECT_EQ(u"Image", extension_descriptions[1]); + EXPECT_EQ(u"All Files", extension_descriptions[2]); // Ensure other file types are allowed. EXPECT_TRUE([panel allowsOtherFileTypes]); @@ -230,8 +228,7 @@ TEST_F(SelectFileDialogMacTest, IncludeAllFiles) { // appropriate extension group to be initially selected. TEST_F(SelectFileDialogMacTest, InitialSelection) { const std::string extensions_arr[][2] = {{"html", "htm"}, {"jpeg", "jpg"}}; - const base::string16 extension_descriptions_arr[] = { - base::ASCIIToUTF16("Webpage"), base::ASCIIToUTF16("Image")}; + const std::u16string extension_descriptions_arr[] = {u"Webpage", u"Image"}; SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back( @@ -239,7 +236,7 @@ TEST_F(SelectFileDialogMacTest, InitialSelection) { file_type_info.extensions.push_back( GetVectorFromArray(extensions_arr[1])); file_type_info.extension_description_overrides = - GetVectorFromArray(extension_descriptions_arr); + GetVectorFromArray(extension_descriptions_arr); FileDialogArguments args = GetDefaultArguments(); args.file_types = &file_type_info; @@ -293,9 +290,7 @@ TEST_F(SelectFileDialogMacTest, InitialSelection) { // extension description is passed for a given extension group. TEST_F(SelectFileDialogMacTest, EmptyDescription) { const std::string extensions_arr[][1] = {{"pdf"}, {"jpg"}, {"qqq"}}; - const base::string16 extension_descriptions_arr[] = { - base::ASCIIToUTF16(""), base::ASCIIToUTF16("Image"), - base::ASCIIToUTF16("")}; + const std::u16string extension_descriptions_arr[] = {u"", u"Image", u""}; SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back( @@ -305,7 +300,7 @@ TEST_F(SelectFileDialogMacTest, EmptyDescription) { file_type_info.extensions.push_back( GetVectorFromArray(extensions_arr[2])); file_type_info.extension_description_overrides = - GetVectorFromArray(extension_descriptions_arr); + GetVectorFromArray(extension_descriptions_arr); FileDialogArguments args(GetDefaultArguments()); args.file_types = &file_type_info; @@ -316,7 +311,7 @@ TEST_F(SelectFileDialogMacTest, EmptyDescription) { EXPECT_TRUE(popup); // Check that the dropdown list created has the correct description. - const std::vector extension_descriptions = + const std::vector extension_descriptions = GetExtensionDescriptionList(popup); EXPECT_EQ(3lu, extension_descriptions.size()); // Verify that the correct system description is produced for known file types @@ -324,12 +319,11 @@ TEST_F(SelectFileDialogMacTest, EmptyDescription) { // string for "PDF" as the system may display: // - Portable Document Format (PDF) // - PDF document - EXPECT_NE(base::string16::npos, - extension_descriptions[0].find(base::ASCIIToUTF16("PDF"))); - EXPECT_EQ(base::ASCIIToUTF16("Image"), extension_descriptions[1]); + EXPECT_NE(std::u16string::npos, extension_descriptions[0].find(u"PDF")); + EXPECT_EQ(u"Image", extension_descriptions[1]); // Verify the description for unknown file types if no extension description // is provided by the client. - EXPECT_EQ(base::ASCIIToUTF16("QQQ File (.qqq)"), extension_descriptions[2]); + EXPECT_EQ(u"QQQ File (.qqq)", extension_descriptions[2]); } // Verify that passing an empty extension list in file_type_info causes the All @@ -345,10 +339,10 @@ TEST_F(SelectFileDialogMacTest, EmptyExtension) { NSPopUpButton* popup = GetPopup(panel); EXPECT_TRUE(popup); - const std::vector extension_descriptions = + const std::vector extension_descriptions = GetExtensionDescriptionList(popup); EXPECT_EQ(1lu, extension_descriptions.size()); - EXPECT_EQ(base::ASCIIToUTF16("All Files"), extension_descriptions[0]); + EXPECT_EQ(u"All Files", extension_descriptions[0]); // Ensure other file types are allowed. EXPECT_TRUE([panel allowsOtherFileTypes]); diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.cc b/chromium/ui/shell_dialogs/select_file_dialog_win.cc index 89705c5b8b8..8a7437c91d2 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_win.cc +++ b/chromium/ui/shell_dialogs/select_file_dialog_win.cc @@ -37,8 +37,8 @@ namespace { // for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't // have an entry for the file type, we return false, true if the description was // found. 'file_ext' must be in form ".txt". -bool GetRegistryDescriptionFromExtension(const base::string16& file_ext, - base::string16* reg_description) { +bool GetRegistryDescriptionFromExtension(const std::u16string& file_ext, + std::u16string* reg_description) { DCHECK(reg_description); base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, base::as_wcstr(file_ext), KEY_READ); @@ -66,12 +66,12 @@ bool GetRegistryDescriptionFromExtension(const base::string16& file_ext, // from the registry. If the file extension does not exist in the registry, a // default description will be created (e.g. "qqq" yields "QQQ File"). std::vector FormatFilterForExtensions( - const std::vector& file_ext, - const std::vector& ext_desc, + const std::vector& file_ext, + const std::vector& ext_desc, bool include_all_files, bool keep_extension_visible) { - const base::string16 all_ext = STRING16_LITERAL("*.*"); - const base::string16 all_desc = + const std::u16string all_ext = u"*.*"; + const std::u16string all_desc = l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES); DCHECK(file_ext.size() >= ext_desc.size()); @@ -83,8 +83,8 @@ std::vector FormatFilterForExtensions( result.reserve(file_ext.size() + 1); for (size_t i = 0; i < file_ext.size(); ++i) { - base::string16 ext = file_ext[i]; - base::string16 desc; + std::u16string ext = file_ext[i]; + std::u16string desc; if (i < ext_desc.size()) desc = ext_desc[i]; @@ -96,18 +96,16 @@ std::vector FormatFilterForExtensions( } if (desc.empty()) { - DCHECK(ext.find(STRING16_LITERAL('.')) != base::string16::npos); - base::string16 first_extension = - ext.substr(ext.find(STRING16_LITERAL('.'))); - size_t first_separator_index = - first_extension.find(STRING16_LITERAL(';')); - if (first_separator_index != base::string16::npos) + DCHECK(ext.find(u'.') != std::u16string::npos); + std::u16string first_extension = ext.substr(ext.find(u'.')); + size_t first_separator_index = first_extension.find(u';'); + if (first_separator_index != std::u16string::npos) first_extension = first_extension.substr(0, first_separator_index); // Find the extension name without the preceeding '.' character. - base::string16 ext_name = first_extension; - size_t ext_index = ext_name.find_first_not_of(STRING16_LITERAL('.')); - if (ext_index != base::string16::npos) + std::u16string ext_name = first_extension; + size_t ext_index = ext_name.find_first_not_of(u'.'); + if (ext_index != std::u16string::npos) ext_name = ext_name.substr(ext_index); if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) { @@ -119,13 +117,12 @@ std::vector FormatFilterForExtensions( include_all_files = true; } if (desc.empty()) - desc = STRING16_LITERAL("*.") + ext_name; + desc = u"*." + ext_name; } else if (keep_extension_visible) { // Having '*' in the description could cause the windows file dialog to // not include the file extension in the file dialog. So strip out any '*' // characters if `keep_extension_visible` is set. - base::ReplaceChars(desc, STRING16_LITERAL("*"), base::StringPiece16(), - &desc); + base::ReplaceChars(desc, u"*", base::StringPiece16(), &desc); } result.push_back({desc, ext}); @@ -166,7 +163,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog, protected: // SelectFileDialog implementation: void SelectFileImpl(Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -218,7 +215,7 @@ SelectFileDialogImpl::~SelectFileDialogImpl() = default; void DoSelectFileOnDialogTaskRunner( const ExecuteSelectFileCallback& execute_select_file_callback, SelectFileDialog::Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const std::vector& filter, int file_type_index, @@ -236,7 +233,7 @@ void DoSelectFileOnDialogTaskRunner( void SelectFileDialogImpl::SelectFileImpl( Type type, - const base::string16& title, + const std::u16string& title, const base::FilePath& default_path, const FileTypeInfo* file_types, int file_type_index, @@ -320,14 +317,14 @@ std::vector SelectFileDialogImpl::GetFilterForFileTypes( if (!file_types) return std::vector(); - std::vector exts; + std::vector exts; for (size_t i = 0; i < file_types->extensions.size(); ++i) { const std::vector& inner_exts = file_types->extensions[i]; - base::string16 ext_string; + std::u16string ext_string; for (size_t j = 0; j < inner_exts.size(); ++j) { if (!ext_string.empty()) - ext_string.push_back(STRING16_LITERAL(';')); - ext_string.append(STRING16_LITERAL("*.")); + ext_string.push_back(u';'); + ext_string.append(u"*."); ext_string.append(base::WideToUTF16(inner_exts[j])); } exts.push_back(ext_string); diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.h b/chromium/ui/shell_dialogs/select_file_dialog_win.h index c699fe29536..f810096577a 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_win.h +++ b/chromium/ui/shell_dialogs/select_file_dialog_win.h @@ -6,11 +6,11 @@ #define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_WIN_H_ #include +#include #include #include #include "base/callback_forward.h" -#include "base/strings/string16.h" #include "ui/gfx/native_widget_types.h" #include "ui/shell_dialogs/execute_select_file_win.h" #include "ui/shell_dialogs/select_file_dialog.h" @@ -27,7 +27,7 @@ struct FileFilterSpec; using ExecuteSelectFileCallback = base::RepeatingCallback& filter, int file_type_index, diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win_unittest.cc b/chromium/ui/shell_dialogs/select_file_dialog_win_unittest.cc index d16397c34fa..991af9fdcbb 100644 --- a/chromium/ui/shell_dialogs/select_file_dialog_win_unittest.cc +++ b/chromium/ui/shell_dialogs/select_file_dialog_win_unittest.cc @@ -14,7 +14,6 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/stl_util.h" -#include "base/strings/string16.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/task_environment.h" @@ -220,7 +219,7 @@ TEST_F(SelectFileDialogWinTest, CancelAllDialogs) { file_type_info_index = 1; } - dialog->SelectFile(test_case.dialog_type, base::string16(), + dialog->SelectFile(test_case.dialog_type, std::u16string(), base::FilePath(), file_type_info.get(), file_type_info_index, std::wstring(), native_window(), nullptr); @@ -248,7 +247,7 @@ TEST_F(SelectFileDialogWinTest, UploadFolderCheckStrings) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_UPLOAD_FOLDER, - base::string16(), default_path, nullptr, 0, L"", + std::u16string(), default_path, nullptr, 0, L"", native_window(), nullptr); // Wait for the window to open and make sure the window title was changed from @@ -275,7 +274,7 @@ TEST_F(SelectFileDialogWinTest, UploadFolderCheckStrings) { // Specifying the title when opening a dialog to select a file, select multiple // files or save a file doesn't do anything. TEST_F(SelectFileDialogWinTest, SpecifyTitle) { - static constexpr base::char16 kTitle[] = STRING16_LITERAL("FooBar Title"); + static constexpr char16_t kTitle[] = u"FooBar Title"; // Create some file in a test folder. base::ScopedTempDir scoped_temp_dir; @@ -316,7 +315,7 @@ TEST_F(SelectFileDialogWinTest, TestSelectFile) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), default_path, nullptr, 0, L"", native_window(), nullptr); // Wait for the window to open @@ -343,7 +342,7 @@ TEST_F(SelectFileDialogWinTest, TestSaveFile) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"", native_window(), nullptr); @@ -367,7 +366,7 @@ TEST_F(SelectFileDialogWinTest, OnlyBasename) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"", native_window(), nullptr); @@ -394,7 +393,7 @@ TEST_F(SelectFileDialogWinTest, SaveAsDifferentExtension) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"html", native_window(), nullptr); @@ -421,7 +420,7 @@ TEST_F(SelectFileDialogWinTest, OpenFileDifferentExtension) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), default_path, &file_type_info, 1, L"html", native_window(), nullptr); @@ -444,7 +443,7 @@ TEST_F(SelectFileDialogWinTest, SelectNonExistingFile) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), default_path, nullptr, 0, L"", native_window(), nullptr); HWND window = WaitForDialogWindow(kSelectFileDefaultTitle); @@ -480,7 +479,7 @@ TEST_F(SelectFileDialogWinTest, SaveFileOverwritePrompt) { scoped_refptr dialog = ui::SelectFileDialog::Create(this, nullptr); - dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), + dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"", native_window(), nullptr); diff --git a/chromium/ui/shell_dialogs/selected_file_info.h b/chromium/ui/shell_dialogs/selected_file_info.h index c7b0ebc3b0b..22f014d5ffb 100644 --- a/chromium/ui/shell_dialogs/selected_file_info.h +++ b/chromium/ui/shell_dialogs/selected_file_info.h @@ -5,11 +5,11 @@ #ifndef UI_SHELL_DIALOGS_SELECTED_FILE_INFO_H_ #define UI_SHELL_DIALOGS_SELECTED_FILE_INFO_H_ +#include #include #include "base/files/file_path.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "ui/shell_dialogs/shell_dialogs_export.h" #include "url/gurl.h" diff --git a/chromium/ui/snapshot/BUILD.gn b/chromium/ui/snapshot/BUILD.gn index 73e9cda8fe3..22e747c9efe 100644 --- a/chromium/ui/snapshot/BUILD.gn +++ b/chromium/ui/snapshot/BUILD.gn @@ -117,4 +117,13 @@ test("snapshot_unittests") { "//ui/wm", ] } + + if (is_fuchsia) { + additional_manifest_fragments = [ + # TODO(crbug.com/1185811): Figure out why jit_capabilities is needed. + "//build/config/fuchsia/test/jit_capabilities.test-cmx", + + "//build/config/fuchsia/test/present_view_capabilities.test-cmx", + ] + } } diff --git a/chromium/ui/snapshot/snapshot_async.cc b/chromium/ui/snapshot/snapshot_async.cc index c450be02128..8e193229c46 100644 --- a/chromium/ui/snapshot/snapshot_async.cc +++ b/chromium/ui/snapshot/snapshot_async.cc @@ -39,7 +39,8 @@ void SnapshotAsync::ScaleCopyOutputResult( GrabWindowSnapshotAsyncCallback callback, const gfx::Size& target_size, std::unique_ptr result) { - const SkBitmap bitmap = result->AsSkBitmap(); + auto scoped_bitmap = result->ScopedAccessSkBitmap(); + auto bitmap = scoped_bitmap.GetOutScopedBitmap(); if (!bitmap.readyToDraw()) { std::move(callback).Run(gfx::Image()); return; @@ -58,7 +59,8 @@ void SnapshotAsync::ScaleCopyOutputResult( void SnapshotAsync::RunCallbackWithCopyOutputResult( GrabWindowSnapshotAsyncCallback callback, std::unique_ptr result) { - const SkBitmap bitmap = result->AsSkBitmap(); + auto scoped_bitmap = result->ScopedAccessSkBitmap(); + auto bitmap = scoped_bitmap.GetOutScopedBitmap(); if (!bitmap.readyToDraw()) { std::move(callback).Run(gfx::Image()); return; diff --git a/chromium/ui/strings/BUILD.gn b/chromium/ui/strings/BUILD.gn index 04a4650def1..09ee0bb51b8 100644 --- a/chromium/ui/strings/BUILD.gn +++ b/chromium/ui/strings/BUILD.gn @@ -17,7 +17,7 @@ group("strings") { grit("ui_strings") { source = "ui_strings.grd" outputs = [ "grit/ui_strings.h" ] - foreach(locale, locales_with_fake_bidi) { + foreach(locale, locales_with_pseudolocales) { outputs += [ "ui_strings_$locale.pak" ] } } @@ -25,7 +25,7 @@ grit("ui_strings") { grit("app_locale_settings") { source = "app_locale_settings.grd" outputs = [ "grit/app_locale_settings.h" ] - foreach(locale, locales_with_fake_bidi) { + foreach(locale, locales_with_pseudolocales) { outputs += [ "app_locale_settings_$locale.pak" ] } } diff --git a/chromium/ui/strings/translations/ui_strings_de.xtb b/chromium/ui/strings/translations/ui_strings_de.xtb index c46456cbabf..440b2fb9e71 100644 --- a/chromium/ui/strings/translations/ui_strings_de.xtb +++ b/chromium/ui/strings/translations/ui_strings_de.xtb @@ -227,7 +227,7 @@ {MAX_UNREAD_NOTIFICATIONS,plural, =1{Mehr als 1 ungelesene Benachrichtigung}other{Mehr als # ungelesene Benachrichtigungen}} {MINUTES,plural, =1{in 1 min}other{in # min}}  +  -Zahl von +Rufnummer von {HOURS,plural, =1{1 Stunde her}other{# Stunden her}} {SECONDS,plural, =1{Noch 1 s}other{Noch # s}} Diese Seite neu laden diff --git a/chromium/ui/strings/translations/ui_strings_es.xtb b/chromium/ui/strings/translations/ui_strings_es.xtb index 877c50f75c3..aa25582339e 100644 --- a/chromium/ui/strings/translations/ui_strings_es.xtb +++ b/chromium/ui/strings/translations/ui_strings_es.xtb @@ -251,7 +251,7 @@ KB/s Busca en el dispositivo, en las aplicaciones, en los ajustes y en la Web. Usa las teclas de flecha para desplazarte por las aplicaciones.  más -Listo +Hecho {HOURS,plural, =1{1 h}other{# h}} Predeterminado Carpeta diff --git a/chromium/ui/strings/translations/ui_strings_fa.xtb b/chromium/ui/strings/translations/ui_strings_fa.xtb index 277c08f5d21..65aef8000a7 100644 --- a/chromium/ui/strings/translations/ui_strings_fa.xtb +++ b/chromium/ui/strings/translations/ui_strings_fa.xtb @@ -146,7 +146,7 @@ اموجی و نمادها برداشتن علامت قفسه در سمت چپ است -‏صفحه بار نشد چون مدول رابط کاربری برنامه‌نویس (dev_ui) نصب نشده است +‏صفحه بار نشد چون مدول میانای کاربر برنامه‌نویس (dev_ui) نصب نشده است سیستم Backspace پیکان چپ diff --git a/chromium/ui/strings/translations/ui_strings_fr-CA.xtb b/chromium/ui/strings/translations/ui_strings_fr-CA.xtb index 6a93df1cd4e..811255c7c2a 100644 --- a/chromium/ui/strings/translations/ui_strings_fr-CA.xtb +++ b/chromium/ui/strings/translations/ui_strings_fr-CA.xtb @@ -146,7 +146,7 @@ Emoji et symboles décocher Étagère à droite -Le chargement de la page a échoué parce que le module d'IU de concepteur (dev_ui) n'est pas installé +Le chargement de la page a échoué parce que le module d'IU de développeur (dev_ui) n'est pas installé Système Effacement arrière Flèche gauche diff --git a/chromium/ui/strings/translations/ui_strings_it.xtb b/chromium/ui/strings/translations/ui_strings_it.xtb index 22e09dfe955..6ef7df6e9dc 100644 --- a/chromium/ui/strings/translations/ui_strings_it.xtb +++ b/chromium/ui/strings/translations/ui_strings_it.xtb @@ -83,7 +83,7 @@ Visualizzazione dei suggerimenti Apri file MB -Shelf a sinistra +Barra delle app a sinistra In basso Ctrl Ripristina @@ -95,7 +95,7 @@ Voce Il testo è troppo grande Contenuti HTML -Shelf nascosto in automatico +Barra delle app nascosta in automatico è stato bloccato {DAYS,plural, =1{1 giorno rimanente}other{# giorni rimanenti}} File @@ -126,7 +126,7 @@ Scorri a destra , valutazione a stelle , consiglio applicazione -Shelf in basso +Barra delle app in basso Centro notifiche, notifiche da leggere USATE SPESSO {MONTHS,plural, =1{1 mese rimasto}other{# mesi rimasti}} @@ -145,13 +145,13 @@ sopra , rilascia per creare una cartella. Emoji e simboli deseleziona -Shelf a destra +Barra delle app a destra Impossibile caricare la pagina perché il modulo UI sviluppatore (dev_ui) non è installato Sistema Backspace Freccia sinistra richiede la tua attenzione. -Elemento shelf +Elemento barra delle app {MINUTES,plural, =1{1 min}other{# min}} {DAYS,plural, =0{Ultima attività: oggi}=1{Ultima attività: 1 giorno fa}other{Ultima attività: # giorni fa}} {DAYS,plural, =1{1 giorno e }other{# giorni e }} @@ -247,7 +247,7 @@ Play/Pausa contenuti multimediali {YEARS,plural, =1{1 a}other{# a}} File (.) -Shelf sempre visualizzato +Barra delle app sempre visualizzata kB/s Cerca sul dispositivo, nelle app, nelle impostazioni e sul Web. Usa i tasti freccia per esplorare le tue app. + altre @@ -260,7 +260,7 @@ Invio in corso... Formato: kB -Shelf sempre nascosto +Barra delle app sempre nascosta Assicurati che il dispositivo sia connesso a Internet. apri {SECONDS,plural, =1{1 sec}other{# sec}} diff --git a/chromium/ui/strings/translations/ui_strings_ky.xtb b/chromium/ui/strings/translations/ui_strings_ky.xtb index 58fd06d0af2..936277ee697 100644 --- a/chromium/ui/strings/translations/ui_strings_ky.xtb +++ b/chromium/ui/strings/translations/ui_strings_ky.xtb @@ -113,7 +113,7 @@ Оң жебе Меню Ке&сүү -Оң кыры +Оң жак чети {UNREAD_NOTIFICATIONS,plural, =1{1 жаңы билдирме}other{# жаңы билдирме}} секир Скриншот @@ -239,7 +239,7 @@ Өтмөк , Колдонмо Он алты түстүү код -Сол кыры +Сол жак чети Өйдө сыдырып кароо {YEARS,plural, =1{1 жыл}other{# жыл}} белгилөө diff --git a/chromium/ui/strings/translations/ui_strings_ne.xtb b/chromium/ui/strings/translations/ui_strings_ne.xtb index 44331a47b77..5e641f12eda 100644 --- a/chromium/ui/strings/translations/ui_strings_ne.xtb +++ b/chromium/ui/strings/translations/ui_strings_ne.xtb @@ -22,7 +22,7 @@ , स्थापना गरिएको एप आदान प्रदान गर्न सकिएन लाई सँग साटियो -तपाईंले यसअघि यो कुरा खोज्नुभएको थियो। आफ्नो इतिहासबाट "" मेटाउनुले तपाईंका सबै यन्त्रमा रहेको तपाईंको खाताबाट यसलाई सदाका लागि हटाउने छ। +तपाईंले यसअघि यो कुरा खोज्नुभएको थियो। आफ्नो इतिहासबाट "" मेटाउनुले तपाईंका सबै डिभाइसमा रहेको तपाईंको खाताबाट यसलाई सदाका लागि हटाउने छ। लन्चर {MINUTES,plural, =1{ १ मिनेट र }other{ # मिनेट र }} सूचना @@ -253,7 +253,7 @@ + थप गरियो {HOURS,plural, =1{१ घन्टा}other{# घन्टा}} -पूर्वनिर्धारित +डिफल्ट फोल्डर छविलाई एनोटेट गर्नुहोस् पछाडि नामक बटन diff --git a/chromium/ui/touch_selection/touch_handle_drawable_aura.cc b/chromium/ui/touch_selection/touch_handle_drawable_aura.cc index 63fe5fe6b6d..fb2e8f88b72 100644 --- a/chromium/ui/touch_selection/touch_handle_drawable_aura.cc +++ b/chromium/ui/touch_selection/touch_handle_drawable_aura.cc @@ -64,7 +64,6 @@ TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent) orientation_(TouchHandleOrientation::UNDEFINED) { window_delegate_->set_image_offset(gfx::Vector2d(kSelectionHandlePadding, kSelectionHandlePadding)); - window_delegate_->set_background_color(SK_ColorTRANSPARENT); window_->SetTransparent(true); window_->Init(LAYER_TEXTURED); window_->set_owned_by_parent(false); diff --git a/chromium/ui/touch_selection/touch_selection_controller.cc b/chromium/ui/touch_selection/touch_selection_controller.cc index 54a85202d21..984501c063b 100644 --- a/chromium/ui/touch_selection/touch_selection_controller.cc +++ b/chromium/ui/touch_selection/touch_selection_controller.cc @@ -4,6 +4,8 @@ #include "ui/touch_selection/touch_selection_controller.h" +#include + #include "base/auto_reset.h" #include "base/check_op.h" #include "base/metrics/histogram_macros.h" @@ -562,8 +564,8 @@ bool TouchSelectionController::ActivateInsertionIfNecessary() { DCHECK_NE(SELECTION_ACTIVE, active_status_); if (!insertion_handle_) { - insertion_handle_.reset( - new TouchHandle(this, TouchHandleOrientation::CENTER, viewport_rect_)); + insertion_handle_ = std::make_unique( + this, TouchHandleOrientation::CENTER, viewport_rect_); } if (active_status_ == INACTIVE || response_pending_input_event_ == TAP || @@ -590,16 +592,16 @@ bool TouchSelectionController::ActivateSelectionIfNecessary() { DCHECK_NE(INSERTION_ACTIVE, active_status_); if (!start_selection_handle_) { - start_selection_handle_.reset( - new TouchHandle(this, start_orientation_, viewport_rect_)); + start_selection_handle_ = + std::make_unique(this, start_orientation_, viewport_rect_); } else { start_selection_handle_->SetEnabled(true); start_selection_handle_->SetViewportRect(viewport_rect_); } if (!end_selection_handle_) { - end_selection_handle_.reset( - new TouchHandle(this, end_orientation_, viewport_rect_)); + end_selection_handle_ = + std::make_unique(this, end_orientation_, viewport_rect_); } else { end_selection_handle_->SetEnabled(true); end_selection_handle_->SetViewportRect(viewport_rect_); diff --git a/chromium/ui/touch_selection/touch_selection_menu_runner.h b/chromium/ui/touch_selection/touch_selection_menu_runner.h index c82e05ebd51..7e72d27b71b 100644 --- a/chromium/ui/touch_selection/touch_selection_menu_runner.h +++ b/chromium/ui/touch_selection/touch_selection_menu_runner.h @@ -38,7 +38,7 @@ class UI_TOUCH_SELECTION_EXPORT TouchSelectionMenuClient { virtual bool ShouldShowQuickMenu() = 0; // Returns the current text selection. - virtual base::string16 GetSelectedText() = 0; + virtual std::u16string GetSelectedText() = 0; }; // An interface for the singleton object responsible for running touch selection diff --git a/chromium/ui/views/BUILD.gn b/chromium/ui/views/BUILD.gn index 07cbdc311c0..c0e55a44f12 100644 --- a/chromium/ui/views/BUILD.gn +++ b/chromium/ui/views/BUILD.gn @@ -196,6 +196,7 @@ component("views") { "focus/focus_manager_factory.h", "focus/focus_search.h", "focus/widget_focus_manager.h", + "image_model_utils.h", "input_event_activation_protector.h", "layout/animating_layout_manager.h", "layout/box_layout.h", @@ -404,6 +405,7 @@ component("views") { "focus/focus_manager_factory.cc", "focus/focus_search.cc", "focus/widget_focus_manager.cc", + "image_model_utils.cc", "input_event_activation_protector.cc", "layout/animating_layout_manager.cc", "layout/box_layout.cc", @@ -505,6 +507,8 @@ component("views") { "//ui/accessibility", "//ui/base/clipboard", "//ui/base/dragdrop/mojom", + "//ui/color", + "//ui/color:mixers", "//ui/display", "//ui/latency", "//ui/native_theme", @@ -525,6 +529,7 @@ component("views") { "//ui/base", "//ui/base/clipboard", "//ui/base/cursor:cursor_base", + "//ui/base/dragdrop:types", "//ui/base/dragdrop/mojom:mojom_headers", "//ui/base/ime/init", "//ui/compositor", @@ -706,6 +711,7 @@ component("views") { "corewm/tooltip.h", "corewm/tooltip_aura.h", "corewm/tooltip_controller.h", + "corewm/tooltip_state_manager.h", "corewm/tooltip_win.h", "event_monitor_aura.h", "touchui/touch_selection_controller_impl.h", @@ -734,6 +740,7 @@ component("views") { "controls/native/native_view_host_aura.cc", "corewm/tooltip_aura.cc", "corewm/tooltip_controller.cc", + "corewm/tooltip_state_manager.cc", "drag_utils_aura.cc", "event_monitor_aura.cc", "metrics_aura.cc", @@ -998,6 +1005,7 @@ source_set("test_support") { "//ui/base", "//ui/base:test_support", "//ui/base/clipboard:clipboard_test_support", + "//ui/base/dragdrop:types", "//ui/base/dragdrop/mojom", "//ui/base/ime/init", "//ui/compositor", @@ -1151,6 +1159,7 @@ test("views_unittests") { "event_monitor_unittest.cc", "focus/focus_manager_unittest.cc", "focus/focus_traversal_unittest.cc", + "image_model_utils_unittest.cc", "layout/animating_layout_manager_unittest.cc", "layout/box_layout_unittest.cc", "layout/box_layout_view_unittest.cc", @@ -1213,6 +1222,7 @@ test("views_unittests") { "//ui/base:test_support", "//ui/base/clipboard", "//ui/base/clipboard:clipboard_test_support", + "//ui/base/dragdrop:types", "//ui/base/dragdrop/mojom", "//ui/base/ime/init", "//ui/compositor:test_support", diff --git a/chromium/ui/views/DEPS b/chromium/ui/views/DEPS index 960c549ee4f..ef048658f58 100644 --- a/chromium/ui/views/DEPS +++ b/chromium/ui/views/DEPS @@ -11,6 +11,7 @@ include_rules = [ "+ui/accessibility", "+ui/aura", "+ui/base", + "+ui/color", "+ui/compositor", "+ui/display", "+ui/events", diff --git a/chromium/ui/views/OWNERS b/chromium/ui/views/OWNERS index 20ee0495499..e244df530c5 100644 --- a/chromium/ui/views/OWNERS +++ b/chromium/ui/views/OWNERS @@ -12,6 +12,7 @@ pkasting@chromium.org robliao@chromium.org sky@chromium.org tapted@chromium.org +tluk@chromium.org weili@chromium.org # Prefer avi@, ellyjones@, lgrey@, or tapted@ for mac specific changes. diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc index a7808998f70..667f30d4fdb 100644 --- a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc +++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc @@ -181,18 +181,21 @@ View* AXAuraObjCache::GetFocusedView() { Widget* focused_widget = focused_widget_for_testing_; aura::Window* focused_window = nullptr; if (!focused_widget) { - if (root_windows_.empty()) - return nullptr; - aura::client::FocusClient* focus_client = - GetFocusClient(*root_windows_.begin()); - if (!focus_client) - return nullptr; - // Uses the a11y override window for focus if it exists, otherwise gets the - // current focused window. - focused_window = a11y_override_window_; - if (!focused_window) - focused_window = focus_client->GetFocusedWindow(); + // last focused window. + focused_window = + a11y_override_window_ ? a11y_override_window_ : focused_window_; + + // Finally, fallback to searching for the focus. + if (!focused_window) { + for (aura::Window* window : root_windows_) { + auto* focus_client = GetFocusClient(window); + if (focus_client && + (focused_window = GetFocusClient(window)->GetFocusedWindow())) { + break; + } + } + } if (!focused_window) return nullptr; @@ -236,6 +239,7 @@ View* AXAuraObjCache::GetFocusedView() { void AXAuraObjCache::OnWindowFocused(aura::Window* gained_focus, aura::Window* lost_focus) { + focused_window_ = gained_focus; OnFocusedViewChanged(); } @@ -249,6 +253,9 @@ void AXAuraObjCache::OnRootWindowObjDestroyed(aura::Window* window) { root_windows_.erase(window); if (root_windows_.empty() && GetFocusClient(window)) GetFocusClient(window)->RemoveObserver(this); + + if (focused_window_ == window) + focused_window_ = nullptr; } void AXAuraObjCache::SetA11yOverrideWindow(aura::Window* a11y_override_window) { diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.h b/chromium/ui/views/accessibility/ax_aura_obj_cache.h index d645a0859b1..1b3931ec72b 100644 --- a/chromium/ui/views/accessibility/ax_aura_obj_cache.h +++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.h @@ -158,6 +158,8 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver { std::set root_windows_; + aura::Window* focused_window_ = nullptr; + views::Widget* focused_widget_for_testing_ = nullptr; }; 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 41ca48dfe7b..7ec62ddd4df 100644 --- a/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc +++ b/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc @@ -103,8 +103,7 @@ TEST_F(AXAuraObjCacheTest, ValidTree) { params.bounds = gfx::Rect(0, 0, 200, 200); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; parent_widget->Init(std::move(params)); - parent_widget->GetNativeWindow()->SetTitle( - base::ASCIIToUTF16("ParentWindow")); + parent_widget->GetNativeWindow()->SetTitle(u"ParentWindow"); parent_widget->Show(); // Create a child window. @@ -115,12 +114,11 @@ TEST_F(AXAuraObjCacheTest, ValidTree) { params.bounds = gfx::Rect(100, 100, 200, 200); params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET; child_widget->Init(std::move(params)); - child_widget->GetNativeWindow()->SetTitle(base::ASCIIToUTF16("ChildWindow")); + child_widget->GetNativeWindow()->SetTitle(u"ChildWindow"); child_widget->Show(); // Create a child view. - auto* button = new LabelButton(Button::PressedCallback(), - base::ASCIIToUTF16("ChildButton")); + auto* button = new LabelButton(Button::PressedCallback(), u"ChildButton"); button->SetSize(gfx::Size(20, 20)); child_widget->GetContentsView()->AddChildView(button); diff --git a/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc index b3a7f26ce54..58ccb4cfc21 100644 --- a/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc +++ b/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc @@ -46,7 +46,11 @@ void AXRootObjWrapper::GetChildren( void AXRootObjWrapper::Serialize(ui::AXNodeData* out_node_data) { out_node_data->id = unique_id_.Get(); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + out_node_data->role = ax::mojom::Role::kClient; +#else out_node_data->role = ax::mojom::Role::kDesktop; +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) display::Screen* screen = display::Screen::GetScreen(); if (!screen) diff --git a/chromium/ui/views/accessibility/ax_system_caret_win_interactive_uitest.cc b/chromium/ui/views/accessibility/ax_system_caret_win_interactive_uitest.cc index 25d4d360f20..f717d33df4a 100644 --- a/chromium/ui/views/accessibility/ax_system_caret_win_interactive_uitest.cc +++ b/chromium/ui/views/accessibility/ax_system_caret_win_interactive_uitest.cc @@ -42,7 +42,7 @@ class AXSystemCaretWinTest : public test::DesktopWidgetTest { widget_->SetBounds(gfx::Rect(0, 0, 200, 200)); textfield_ = new Textfield(); textfield_->SetBounds(0, 0, 200, 20); - textfield_->SetText(base::ASCIIToUTF16("Some text.")); + textfield_->SetText(u"Some text."); widget_->GetRootView()->AddChildView(textfield_); test::WidgetActivationWaiter waiter(widget_, true); widget_->Show(); @@ -342,7 +342,7 @@ TEST_F(AXSystemCaretWinTest, TestCaretMSAAEvents) { { // Move focus to a button. - LabelButton button{Button::PressedCallback(), base::string16()}; + LabelButton button{Button::PressedCallback(), std::u16string()}; button.SetBounds(500, 0, 200, 20); widget_->GetRootView()->AddChildView(&button); test::WidgetActivationWaiter waiter(widget_, true); diff --git a/chromium/ui/views/accessibility/ax_tree_source_views.h b/chromium/ui/views/accessibility/ax_tree_source_views.h index f6c02549042..02d709a4f93 100644 --- a/chromium/ui/views/accessibility/ax_tree_source_views.h +++ b/chromium/ui/views/accessibility/ax_tree_source_views.h @@ -60,7 +60,7 @@ class VIEWS_EXPORT AXTreeSourceViews // Useful for debugging. std::string ToString(views::AXAuraObjWrapper* root, std::string prefix); - const ui::AXTreeID tree_id_for_test() const { return tree_id_; } + const ui::AXTreeID tree_id() const { return tree_id_; } private: // The top-level object to use for the AX tree. See class comment. diff --git a/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc b/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc index 4f0f799ec48..a2d54aa345e 100644 --- a/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc +++ b/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc @@ -52,11 +52,11 @@ class AXTreeSourceViewsTest : public ViewsTestBase { widget_->Init(std::move(params)); widget_->SetContentsView(std::make_unique()); - label1_ = new Label(base::ASCIIToUTF16("Label 1")); + label1_ = new Label(u"Label 1"); label1_->SetBounds(1, 1, 111, 111); widget_->GetContentsView()->AddChildView(label1_); - label2_ = new Label(base::ASCIIToUTF16("Label 2")); + label2_ = new Label(u"Label 2"); label2_->SetBounds(2, 2, 222, 222); widget_->GetContentsView()->AddChildView(label2_); @@ -152,5 +152,20 @@ TEST_F(AXTreeSourceViewsTest, IgnoredView) { EXPECT_TRUE(tree.IsValid(cache.GetOrCreate(ignored_view))); } +TEST_F(AXTreeSourceViewsTest, ViewWithChildTreeHasNoChildren) { + View* contents_view = widget_->GetContentsView(); + contents_view->GetViewAccessibility().OverrideChildTreeID( + ui::AXTreeID::CreateNewAXTreeID()); + + AXAuraObjCache cache; + TestAXTreeSourceViews tree(cache.GetOrCreate(widget_.get()), &cache); + auto* ax_obj = cache.GetOrCreate(contents_view); + EXPECT_TRUE(tree.IsValid(ax_obj)); + std::vector children; + ax_obj->GetChildren(&children); + EXPECT_TRUE(children.empty()); + EXPECT_EQ(nullptr, cache.GetOrCreate(textfield_)->GetParent()); +} + } // namespace } // namespace views diff --git a/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc index a751656bf33..c1a919510ce 100644 --- a/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc +++ b/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc @@ -30,8 +30,13 @@ AXAuraObjWrapper* AXViewObjWrapper::GetParent() { if (!view_) return nullptr; - if (view_->parent()) + if (view_->parent()) { + if (view_->parent()->GetViewAccessibility().GetChildTreeID() != + ui::AXTreeIDUnknown()) + return nullptr; + return aura_obj_cache_->GetOrCreate(view_->parent()); + } if (view_->GetWidget()) return aura_obj_cache_->GetOrCreate(view_->GetWidget()); @@ -45,6 +50,11 @@ void AXViewObjWrapper::GetChildren( return; const ViewAccessibility& view_accessibility = view_->GetViewAccessibility(); + + // Ignore this view's descendants if it has a child tree. + if (view_accessibility.GetChildTreeID() != ui::AXTreeIDUnknown()) + return; + if (view_accessibility.IsLeaf()) return; diff --git a/chromium/ui/views/accessibility/ax_virtual_view.h b/chromium/ui/views/accessibility/ax_virtual_view.h index fdab3993dce..9ef022c9319 100644 --- a/chromium/ui/views/accessibility/ax_virtual_view.h +++ b/chromium/ui/views/accessibility/ax_virtual_view.h @@ -8,10 +8,10 @@ #include #include +#include #include #include "base/callback_forward.h" -#include "base/strings/string16.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" diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc index cc34462e2f3..53a80920ac0 100644 --- a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc +++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc @@ -16,6 +16,9 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_tree_id.h" #include "ui/aura/client/focus_client.h" +#include "ui/aura/window_tree_host.h" +#include "ui/aura/window_tree_host_platform.h" +#include "ui/platform_window/platform_window.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" #include "ui/views/widget/widget.h" @@ -103,11 +106,24 @@ AXAuraObjWrapper* AXWindowObjWrapper::GetParent() { if (!parent) return nullptr; + if (parent->GetProperty(ui::kChildAXTreeID) && + ui::AXTreeID::FromString(*(parent->GetProperty(ui::kChildAXTreeID))) != + ui::AXTreeIDUnknown()) { + return nullptr; + } + return aura_obj_cache_->GetOrCreate(parent); } void AXWindowObjWrapper::GetChildren( std::vector* out_children) { + // Ignore this window's descendants if it has a child tree. + if (window_->GetProperty(ui::kChildAXTreeID) && + ui::AXTreeID::FromString(*(window_->GetProperty(ui::kChildAXTreeID))) != + ui::AXTreeIDUnknown()) { + return; + } + for (auto* child : window_->children()) out_children->push_back(aura_obj_cache_->GetOrCreate(child)); @@ -118,6 +134,27 @@ void AXWindowObjWrapper::GetChildren( } void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // This is a top level root window. + if (window_->IsRootWindow() && !window_->parent()) { + // On desktop aura there is one WindowTreeHost per top-level window. + aura::WindowTreeHost* window_tree_host = window_->GetHost(); + if (window_tree_host) { + // Lacros is based on Ozone/Wayland, which uses PlatformWindow and + // aura::WindowTreeHostPlatform. + aura::WindowTreeHostPlatform* window_tree_host_platform = + static_cast(window_tree_host); + + const std::string window_id = + window_tree_host_platform->platform_window()->GetWindowUniqueId(); + + if (!window_id.empty()) + out_node_data->AddStringAttribute( + ax::mojom::StringAttribute::kParentTreeNodeAppId, window_id); + } + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + out_node_data->id = GetUniqueId(); ax::mojom::Role role = window_->GetProperty(ui::kAXRoleOverride); if (role != ax::mojom::Role::kNone) @@ -132,25 +169,27 @@ void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) { out_node_data->relative_bounds.bounds = gfx::RectF(window_->GetBoundsInScreen()); std::string* child_ax_tree_id_ptr = window_->GetProperty(ui::kChildAXTreeID); - if (child_ax_tree_id_ptr && ui::AXTreeID::FromString(*child_ax_tree_id_ptr) != - ui::AXTreeIDUnknown()) { - // Most often, child AX trees are parented to Views. We need to handle - // the case where they're not here, but we don't want the same AX tree - // to be a child of two different parents. - // - // To avoid this double-parenting, only add the child tree ID of this - // window if the top-level window doesn't have an associated Widget. - // - // Also, if this window is not visible, its child tree should also be - // non-visible so prune it. - if (!window_->GetToplevelWindow() || - GetWidgetForWindow(window_->GetToplevelWindow()) || - !window_->IsVisible()) { - return; + if (child_ax_tree_id_ptr) { + ui::AXTreeID child_ax_tree_id = + ui::AXTreeID::FromString(*child_ax_tree_id_ptr); + if (child_ax_tree_id != ui::AXTreeIDUnknown()) { + // Most often, child AX trees are parented to Views. We need to handle + // the case where they're not here, but we don't want the same AX tree + // to be a child of two different parents. + // + // To avoid this double-parenting, only add the child tree ID of this + // window if the top-level window doesn't have an associated Widget. + // + // Also, if this window is not visible, its child tree should also be + // non-visible so prune it. + if (!window_->GetToplevelWindow() || + GetWidgetForWindow(window_->GetToplevelWindow()) || + !window_->IsVisible()) { + return; + } + + out_node_data->AddChildTreeId(child_ax_tree_id); } - - out_node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - *child_ax_tree_id_ptr); } out_node_data->AddStringAttribute(ax::mojom::StringAttribute::kClassName, diff --git a/chromium/ui/views/accessibility/view_accessibility.cc b/chromium/ui/views/accessibility/view_accessibility.cc index a2914dbb74e..8cfb389ab99 100644 --- a/chromium/ui/views/accessibility/view_accessibility.cc +++ b/chromium/ui/views/accessibility/view_accessibility.cc @@ -211,6 +211,7 @@ void ViewAccessibility::GetAccessibleNodeData(ui::AXNodeData* data) const { } static constexpr ax::mojom::IntListAttribute kOverridableIntListAttributes[]{ + ax::mojom::IntListAttribute::kLabelledbyIds, ax::mojom::IntListAttribute::kDescribedbyIds, }; for (auto attribute : kOverridableIntListAttributes) { @@ -220,7 +221,7 @@ void ViewAccessibility::GetAccessibleNodeData(ui::AXNodeData* data) const { } if (!data->HasStringAttribute(ax::mojom::StringAttribute::kDescription)) { - base::string16 tooltip = view_->GetTooltipText(gfx::Point()); + std::u16string tooltip = view_->GetTooltipText(gfx::Point()); // Some screen readers announce the accessible description right after the // accessible name. Only use the tooltip as the accessible description if // it's different from the name, otherwise users might be puzzled as to why @@ -270,6 +271,13 @@ void ViewAccessibility::GetAccessibleNodeData(ui::AXNodeData* data) const { if (view_->context_menu_controller()) data->AddAction(ax::mojom::Action::kShowContextMenu); + + DCHECK(!data->HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId)) + << "Please annotate child tree ids using " + "ViewAccessibility::OverrideChildTreeID."; + if (child_tree_id_) { + data->AddChildTreeId(child_tree_id_.value()); + } } void ViewAccessibility::OverrideFocus(AXVirtualView* virtual_view) { @@ -327,7 +335,7 @@ void ViewAccessibility::OverrideName(const std::string& name) { custom_data_.SetName(name); } -void ViewAccessibility::OverrideName(const base::string16& name) { +void ViewAccessibility::OverrideName(const std::u16string& name) { custom_data_.SetName(name); } @@ -335,7 +343,7 @@ void ViewAccessibility::OverrideDescription(const std::string& description) { custom_data_.SetDescription(description); } -void ViewAccessibility::OverrideDescription(const base::string16& description) { +void ViewAccessibility::OverrideDescription(const std::u16string& description) { custom_data_.SetDescription(description); } @@ -395,8 +403,15 @@ void ViewAccessibility::OverrideBounds(const gfx::RectF& bounds) { custom_data_.relative_bounds.bounds = bounds; } +void ViewAccessibility::OverrideLabelledBy(View* labelled_by_view) { + int32_t labelled_by_id = + labelled_by_view->GetViewAccessibility().GetUniqueId().Get(); + custom_data_.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds, + {labelled_by_id}); +} + void ViewAccessibility::OverrideDescribedBy(View* described_by_view) { - int described_by_id = + int32_t described_by_id = described_by_view->GetViewAccessibility().GetUniqueId().Get(); custom_data_.AddIntListAttribute(ax::mojom::IntListAttribute::kDescribedbyIds, {described_by_id}); @@ -427,6 +442,17 @@ Widget* ViewAccessibility::GetPreviousFocus() const { return previous_focus_; } +void ViewAccessibility::OverrideChildTreeID(ui::AXTreeID tree_id) { + if (tree_id == ui::AXTreeIDUnknown()) + child_tree_id_ = base::nullopt; + else + child_tree_id_ = tree_id; +} + +ui::AXTreeID ViewAccessibility::GetChildTreeID() const { + return child_tree_id_ ? *child_tree_id_ : ui::AXTreeIDUnknown(); +} + gfx::NativeViewAccessible ViewAccessibility::GetNativeObject() const { return nullptr; } @@ -438,7 +464,7 @@ void ViewAccessibility::NotifyAccessibilityEvent(ax::mojom::Event event_type) { accessibility_events_callback_.Run(nullptr, event_type); } -void ViewAccessibility::AnnounceText(const base::string16& text) { +void ViewAccessibility::AnnounceText(const std::u16string& text) { Widget* const widget = view_->GetWidget(); if (!widget) return; diff --git a/chromium/ui/views/accessibility/view_accessibility.h b/chromium/ui/views/accessibility/view_accessibility.h index 7c8004b2c6b..ccd4dd42fe8 100644 --- a/chromium/ui/views/accessibility/view_accessibility.h +++ b/chromium/ui/views/accessibility/view_accessibility.h @@ -11,7 +11,6 @@ #include "base/callback_forward.h" #include "base/optional.h" -#include "base/strings/string16.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "ui/accessibility/ax_enums.mojom-forward.h" @@ -100,9 +99,9 @@ class VIEWS_EXPORT ViewAccessibility { void OverrideRole(const ax::mojom::Role role); void OverrideName(const std::string& name); - void OverrideName(const base::string16& name); + void OverrideName(const std::u16string& name); void OverrideDescription(const std::string& description); - void OverrideDescription(const base::string16& description); + void OverrideDescription(const std::u16string& description); // Sets whether this View hides all its descendants from the accessibility // tree that is exposed to platform APIs. This is similar, but not exactly @@ -136,6 +135,7 @@ class VIEWS_EXPORT ViewAccessibility { virtual bool IsAccessibilityEnabled() const; void OverrideBounds(const gfx::RectF& bounds); + void OverrideLabelledBy(View* labelled_by_view); void OverrideDescribedBy(View* described_by_view); void OverrideHasPopup(const ax::mojom::HasPopup has_popup); @@ -157,6 +157,10 @@ class VIEWS_EXPORT ViewAccessibility { Widget* GetNextFocus() const; Widget* GetPreviousFocus() const; + // Override the child tree id. + void OverrideChildTreeID(ui::AXTreeID tree_id); + ui::AXTreeID GetChildTreeID() const; + // Returns the accessibility object that represents the View whose // accessibility is managed by this instance. This may be an AXPlatformNode or // it may be a native accessible object implemented by another class. @@ -166,7 +170,7 @@ class VIEWS_EXPORT ViewAccessibility { // Causes the screen reader to announce |text|. If the current user is not // using a screen reader, has no effect. - virtual void AnnounceText(const base::string16& text); + virtual void AnnounceText(const std::u16string& text); virtual const ui::AXUniqueId& GetUniqueId() const; @@ -264,6 +268,9 @@ class VIEWS_EXPORT ViewAccessibility { Widget* next_focus_ = nullptr; Widget* previous_focus_ = nullptr; + // This view's child tree id. + base::Optional child_tree_id_; + #if defined(USE_AURA) && !BUILDFLAG(IS_CHROMEOS_ASH) // Each instance of ViewAccessibility that's associated with a root View // owns an ViewsAXTreeManager. For other Views, this should be nullptr. 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 3c427e8e606..dfcc3aa88c2 100644 --- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc +++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc @@ -263,7 +263,7 @@ void ViewAXPlatformNodeDelegate::NotifyAccessibilityEvent( } #if defined(OS_APPLE) -void ViewAXPlatformNodeDelegate::AnnounceText(const base::string16& text) { +void ViewAXPlatformNodeDelegate::AnnounceText(const std::u16string& text) { ax_platform_node_->AnnounceText(text); } #endif // defined(OS_APPLE) @@ -629,15 +629,15 @@ bool ViewAXPlatformNodeDelegate::IsOffscreen() const { return false; } -base::string16 ViewAXPlatformNodeDelegate::GetAuthorUniqueId() const { +std::u16string ViewAXPlatformNodeDelegate::GetAuthorUniqueId() const { const View* v = view(); if (v) { const int view_id = v->GetID(); if (view_id) - return base::WideToUTF16(L"view_") + base::NumberToString16(view_id); + return u"view_" + base::NumberToString16(view_id); } - return base::string16(); + return std::u16string(); } bool ViewAXPlatformNodeDelegate::IsMinimized() const { 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 cc0297fd1f2..04b5412ef25 100644 --- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h +++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h @@ -7,10 +7,10 @@ #include +#include #include #include "base/optional.h" -#include "base/strings/string16.h" #include "build/build_config.h" #include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/accessibility/ax_node_data.h" @@ -55,7 +55,7 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility, gfx::NativeViewAccessible GetNativeObject() const override; void NotifyAccessibilityEvent(ax::mojom::Event event_type) override; #if defined(OS_APPLE) - void AnnounceText(const base::string16& text) override; + void AnnounceText(const std::u16string& text) override; #endif // ui::AXPlatformNodeDelegate. @@ -89,7 +89,7 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility, bool AccessibilityPerformAction(const ui::AXActionData& data) override; bool ShouldIgnoreHoveredStateForTesting() override; bool IsOffscreen() const override; - base::string16 GetAuthorUniqueId() const override; + std::u16string GetAuthorUniqueId() const override; bool IsMinimized() const override; // Also in |ViewAccessibility|. const ui::AXUniqueId& GetUniqueId() const override; 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 ea0c81b3b83..09c03eb21b1 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 @@ -33,7 +33,7 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) { View* content = widget.SetContentsView(std::make_unique()); Textfield* textfield = new Textfield; - textfield->SetAccessibleName(base::UTF8ToUTF16("Name")); + textfield->SetAccessibleName(u"Name"); content->AddChildView(textfield); ASSERT_EQ(0, atk_object_get_n_accessible_children( @@ -59,7 +59,7 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) { g_signal_connect(atk_text, "text-insert", callback, &text_insert_events); g_signal_connect(atk_text, "text-remove", callback, &text_remove_events); - textfield->SetText(base::UTF8ToUTF16("Value")); + textfield->SetText(u"Value"); ASSERT_EQ(text_remove_events.size(), 0ul); ASSERT_EQ(text_insert_events.size(), 1ul); EXPECT_EQ(text_insert_events[0].position, 0); @@ -67,7 +67,7 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) { EXPECT_EQ(text_insert_events[0].text, "Value"); text_insert_events.clear(); - textfield->SetText(base::UTF8ToUTF16("Value A")); + textfield->SetText(u"Value A"); ASSERT_EQ(text_remove_events.size(), 0ul); ASSERT_EQ(text_insert_events.size(), 1ul); EXPECT_EQ(text_insert_events[0].position, 5); @@ -75,7 +75,7 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) { EXPECT_EQ(text_insert_events[0].text, " A"); text_insert_events.clear(); - textfield->SetText(base::UTF8ToUTF16("Value")); + textfield->SetText(u"Value"); ASSERT_EQ(text_remove_events.size(), 1ul); ASSERT_EQ(text_insert_events.size(), 0ul); EXPECT_EQ(text_remove_events[0].position, 5); @@ -83,7 +83,7 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) { EXPECT_EQ(text_remove_events[0].text, " A"); text_remove_events.clear(); - textfield->SetText(base::UTF8ToUTF16("Prefix Value")); + textfield->SetText(u"Prefix Value"); ASSERT_EQ(text_remove_events.size(), 0ul); ASSERT_EQ(text_insert_events.size(), 1ul); EXPECT_EQ(text_insert_events[0].position, 0); @@ -91,7 +91,7 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) { EXPECT_EQ(text_insert_events[0].text, "Prefix "); text_insert_events.clear(); - textfield->SetText(base::UTF8ToUTF16("Value")); + textfield->SetText(u"Value"); ASSERT_EQ(text_remove_events.size(), 1ul); ASSERT_EQ(text_insert_events.size(), 0ul); EXPECT_EQ(text_remove_events[0].position, 0); 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 7c0f11eea2f..d34d57d1451 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 @@ -80,9 +80,9 @@ class TestTableModel : public ui::TableModel { // ui::TableModel: int RowCount() override { return 10; } - base::string16 GetText(int row, int column_id) override { + std::u16string GetText(int row, int column_id) override { if (row == -1) - return base::string16(); + return std::u16string(); const char* const cells[5][4] = { {"Orange", "Orange", "South america", "$5"}, @@ -260,23 +260,21 @@ class ViewAXPlatformNodeDelegateMenuTest menu_ = new views::TestMenuItemView(menu_delegate_.get()); runner_ = std::make_unique(menu_, 0); - menu_->AppendMenuItemImpl(0, base::ASCIIToUTF16("normal"), gfx::ImageSkia(), + menu_->AppendMenuItemImpl(0, u"normal", gfx::ImageSkia(), MenuItemView::Type::kNormal); - menu_->AppendMenuItemImpl(1, base::ASCIIToUTF16("submenu"), - gfx::ImageSkia(), MenuItemView::Type::kSubMenu); - menu_->AppendMenuItemImpl(2, base::ASCIIToUTF16("actionable"), - gfx::ImageSkia(), + menu_->AppendMenuItemImpl(1, u"submenu", gfx::ImageSkia(), + MenuItemView::Type::kSubMenu); + menu_->AppendMenuItemImpl(2, u"actionable", gfx::ImageSkia(), MenuItemView::Type::kActionableSubMenu); - menu_->AppendMenuItemImpl(3, base::ASCIIToUTF16("checkbox"), - gfx::ImageSkia(), MenuItemView::Type::kCheckbox); - menu_->AppendMenuItemImpl(4, base::ASCIIToUTF16("radio"), gfx::ImageSkia(), + menu_->AppendMenuItemImpl(3, u"checkbox", gfx::ImageSkia(), + MenuItemView::Type::kCheckbox); + menu_->AppendMenuItemImpl(4, u"radio", gfx::ImageSkia(), MenuItemView::Type::kRadio); - menu_->AppendMenuItemImpl(5, base::ASCIIToUTF16("separator"), - gfx::ImageSkia(), MenuItemView::Type::kSeparator); - menu_->AppendMenuItemImpl(6, base::ASCIIToUTF16("highlighted"), - gfx::ImageSkia(), + menu_->AppendMenuItemImpl(5, u"separator", gfx::ImageSkia(), + MenuItemView::Type::kSeparator); + menu_->AppendMenuItemImpl(6, u"highlighted", gfx::ImageSkia(), MenuItemView::Type::kHighlighted); - menu_->AppendMenuItemImpl(7, base::ASCIIToUTF16("title"), gfx::ImageSkia(), + menu_->AppendMenuItemImpl(7, u"title", gfx::ImageSkia(), MenuItemView::Type::kTitle); submenu_ = menu_->GetSubmenu(); @@ -415,12 +413,11 @@ TEST_F(ViewAXPlatformNodeDelegateTest, SetFocus) { } TEST_F(ViewAXPlatformNodeDelegateTest, GetAuthorUniqueIdDefault) { - ASSERT_EQ(base::WideToUTF16(L""), label_accessibility()->GetAuthorUniqueId()); + ASSERT_EQ(u"", label_accessibility()->GetAuthorUniqueId()); } TEST_F(ViewAXPlatformNodeDelegateTest, GetAuthorUniqueIdNonDefault) { - ASSERT_EQ(base::WideToUTF16(L"view_1"), - button_accessibility()->GetAuthorUniqueId()); + ASSERT_EQ(u"view_1", button_accessibility()->GetAuthorUniqueId()); } TEST_F(ViewAXPlatformNodeDelegateTest, IsOrderedSet) { 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 ab3d076e524..92ee0e6eb8d 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 @@ -102,8 +102,8 @@ TEST_F(ViewAXPlatformNodeDelegateWinTest, TextfieldAccessibility) { View* content = widget.SetContentsView(std::make_unique()); Textfield* textfield = new Textfield; - textfield->SetAccessibleName(STRING16_LITERAL("Name")); - textfield->SetText(STRING16_LITERAL("Value")); + textfield->SetAccessibleName(u"Name"); + textfield->SetText(u"Value"); content->AddChildView(textfield); ComPtr content_accessible(content->GetNativeViewAccessible()); @@ -137,7 +137,7 @@ TEST_F(ViewAXPlatformNodeDelegateWinTest, TextfieldAccessibility) { ScopedBstr new_value(L"New value"); ASSERT_EQ(S_OK, textfield_accessible->put_accValue(childid_self, new_value.Get())); - EXPECT_EQ(STRING16_LITERAL("New value"), textfield->GetText()); + EXPECT_EQ(u"New value", textfield->GetText()); } TEST_F(ViewAXPlatformNodeDelegateWinTest, TextfieldAssociatedLabel) { @@ -148,7 +148,7 @@ TEST_F(ViewAXPlatformNodeDelegateWinTest, TextfieldAssociatedLabel) { View* content = widget.SetContentsView(std::make_unique()); - Label* label = new Label(STRING16_LITERAL("Label")); + Label* label = new Label(u"Label"); content->AddChildView(label); Textfield* textfield = new Textfield; textfield->SetAssociatedLabel(label); @@ -394,7 +394,7 @@ TEST_F(ViewAXPlatformNodeDelegateWinTest, Overrides) { View* alert_view = new ScrollView; alert_view->GetViewAccessibility().OverrideRole(ax::mojom::Role::kAlert); - alert_view->GetViewAccessibility().OverrideName(STRING16_LITERAL("Name")); + alert_view->GetViewAccessibility().OverrideName(u"Name"); alert_view->GetViewAccessibility().OverrideDescription("Description"); alert_view->GetViewAccessibility().OverrideIsLeaf(true); contents_view->AddChildView(alert_view); @@ -555,9 +555,9 @@ class TestTableModel : public ui::TableModel { // ui::TableModel: int RowCount() override { return 3; } - base::string16 GetText(int row, int column_id) override { + std::u16string GetText(int row, int column_id) override { if (row == -1) - return base::string16(); + return std::u16string(); const char* const cells[5][3] = { {"Australia", "24,584,620", "1,323,421,072,479"}, diff --git a/chromium/ui/views/accessible_pane_view_unittest.cc b/chromium/ui/views/accessible_pane_view_unittest.cc index 9408c37ef13..91972aa1ef7 100644 --- a/chromium/ui/views/accessible_pane_view_unittest.cc +++ b/chromium/ui/views/accessible_pane_view_unittest.cc @@ -54,7 +54,7 @@ TestBarView::~TestBarView() = default; void TestBarView::Init() { SetLayoutManager(std::make_unique()); - base::string16 label; + std::u16string label; child_button_ = AddChildView(std::make_unique()); second_child_button_ = AddChildView(std::make_unique()); third_child_button_ = AddChildView(std::make_unique()); diff --git a/chromium/ui/views/border.h b/chromium/ui/views/border.h index 003fb79ac82..7e9e1ed65a8 100644 --- a/chromium/ui/views/border.h +++ b/chromium/ui/views/border.h @@ -28,8 +28,10 @@ class View; // Border class. // // The border class is used to display a border around a view. -// To set a border on a view, just call SetBorder on the view, for example: -// view->SetBorder(CreateSolidBorder(1, SkColorSetRGB(25, 25, 112)); +// To set a border on a view, call SetBorder on the view, for example: +// view->SetBorder(CreateSolidBorder(1, view->GetNativeTheme()->GetSystemColor( +// ui::NativeTheme::kColorId_UnfocusedBorderColor))); +// Make sure the border color is updated on theme changes. // Once set on a view, the border is owned by the view. // // IMPORTANT NOTE: not all views support borders at this point. In order to @@ -109,8 +111,10 @@ VIEWS_EXPORT std::unique_ptr CreateSolidSidedBorder(int top, // equivalent to changing the insets of |border| without changing how or what it // paints. Example: // -// view->SetBorder(CreatePaddedBorder(CreateSolidBorder(1, SK_ColorRED), -// gfx::Insets(2, 0, 0, 0))); +// view->SetBorder(CreatePaddedBorder( +// CreateSolidBorder(1, view->GetNativeTheme()->GetSystemColor( +// ui::NativeTheme::kColorId_UnfocusedBorderColor)), +// gfx::Insets(2, 0, 0, 0))); // // yields a single dip red border and an additional 2dip of unpainted padding // above the view content (below the border). diff --git a/chromium/ui/views/border_unittest.cc b/chromium/ui/views/border_unittest.cc index 77232b0bf19..51504c5562e 100644 --- a/chromium/ui/views/border_unittest.cc +++ b/chromium/ui/views/border_unittest.cc @@ -209,7 +209,7 @@ TEST_F(BorderTest, SolidBorder) { TEST_F(BorderTest, RoundedRectBorder) { std::unique_ptr border(CreateRoundedRectBorder( - 3, LayoutProvider::Get()->GetCornerRadiusMetric(EMPHASIS_LOW), + 3, LayoutProvider::Get()->GetCornerRadiusMetric(Emphasis::kLow), SK_ColorBLUE)); EXPECT_EQ(gfx::Size(6, 6), border->GetMinimumSize()); EXPECT_EQ(gfx::Insets(3, 3, 3, 3), border->GetInsets()); 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 1e26b9e0264..da5c3df3d05 100644 --- a/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc +++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc @@ -69,8 +69,8 @@ class TestBubbleDialogDelegateView : public BubbleDialogDelegateView { GetBubbleFrameView()->SetTitleView(std::move(title_view_)); } - base::string16 GetWindowTitle() const override { - return base::ASCIIToUTF16("TITLE TITLE TITLE"); + std::u16string GetWindowTitle() const override { + return u"TITLE TITLE TITLE"; } bool ShouldShowWindowTitle() const override { @@ -505,7 +505,7 @@ TEST_F(BubbleDialogDelegateViewTest, StyledLabelTitle) { new TestBubbleDialogDelegateView(anchor_widget->GetContentsView()); StyledLabel* title_view = bubble_delegate->set_title_view(std::make_unique()); - title_view->SetText(base::ASCIIToUTF16("123")); + title_view->SetText(u"123"); Widget* bubble_widget = BubbleDialogDelegateView::CreateBubble(bubble_delegate); @@ -513,7 +513,7 @@ TEST_F(BubbleDialogDelegateViewTest, StyledLabelTitle) { const gfx::Size size_before_new_title = bubble_widget->GetWindowBoundsInScreen().size(); - title_view->SetText(base::ASCIIToUTF16("12")); + title_view->SetText(u"12"); bubble_delegate->SizeToContents(); // A shorter title should change nothing, since both will be within the @@ -537,7 +537,7 @@ TEST_F(BubbleDialogDelegateViewTest, AttachedWidgetShowsInkDropWhenVisible) { std::unique_ptr anchor_widget = CreateTestWidget(); LabelButton* button = anchor_widget->SetContentsView(std::make_unique( - Button::PressedCallback(), base::string16())); + Button::PressedCallback(), std::u16string())); TestInkDrop* ink_drop = new TestInkDrop(); test::InkDropHostViewTestApi(button).SetInkDrop(base::WrapUnique(ink_drop)); TestBubbleDialogDelegateView* bubble_delegate = @@ -566,7 +566,7 @@ TEST_F(BubbleDialogDelegateViewTest, VisibleWidgetShowsInkDropOnAttaching) { std::unique_ptr anchor_widget = CreateTestWidget(); LabelButton* button = anchor_widget->SetContentsView(std::make_unique( - Button::PressedCallback(), base::string16())); + Button::PressedCallback(), std::u16string())); TestInkDrop* ink_drop = new TestInkDrop(); test::InkDropHostViewTestApi(button).SetInkDrop(base::WrapUnique(ink_drop)); TestBubbleDialogDelegateView* bubble_delegate = diff --git a/chromium/ui/views/bubble/bubble_dialog_model_host.cc b/chromium/ui/views/bubble/bubble_dialog_model_host.cc index cee4c6b6ac6..09dd2414288 100644 --- a/chromium/ui/views/bubble/bubble_dialog_model_host.cc +++ b/chromium/ui/views/bubble/bubble_dialog_model_host.cc @@ -515,7 +515,7 @@ void BubbleDialogModelHost::AddOrUpdateTextfield( void BubbleDialogModelHost::AddViewForLabelAndField( ui::DialogModelField* model_field, - const base::string16& label_text, + const std::u16string& label_text, std::unique_ptr field, const gfx::FontList& field_font) { auto box_layout = std::make_unique(); @@ -620,9 +620,9 @@ BubbleDialogModelHost::CreateStyledLabelForDialogModelLabel( DCHECK_EQ(dialog_label.links(GetPassKey()).size(), 1u); size_t offset; - const base::string16 link_text = l10n_util::GetStringUTF16( + const std::u16string link_text = l10n_util::GetStringUTF16( dialog_label.links(GetPassKey()).front().message_id); - const base::string16 text = l10n_util::GetStringFUTF16( + const std::u16string text = l10n_util::GetStringFUTF16( dialog_label.message_id(GetPassKey()), link_text, &offset); auto styled_label = std::make_unique(); diff --git a/chromium/ui/views/bubble/bubble_dialog_model_host.h b/chromium/ui/views/bubble/bubble_dialog_model_host.h index 9f05a03c38b..c6da96b457c 100644 --- a/chromium/ui/views/bubble/bubble_dialog_model_host.h +++ b/chromium/ui/views/bubble/bubble_dialog_model_host.h @@ -103,7 +103,7 @@ class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView, void UpdateSpacingAndMargins(); void AddViewForLabelAndField(ui::DialogModelField* model_field, - const base::string16& label_text, + const std::u16string& label_text, std::unique_ptr field, const gfx::FontList& field_font); diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc index f29e4ce60ec..a2380fa3ac5 100644 --- a/chromium/ui/views/bubble/bubble_frame_view.cc +++ b/chromium/ui/views/bubble/bubble_frame_view.cc @@ -24,6 +24,7 @@ #include "ui/native_theme/native_theme.h" #include "ui/resources/grit/ui_resources.h" #include "ui/strings/grit/ui_strings.h" +#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/bubble/footnote_container_view.h" #include "ui/views/controls/button/image_button.h" @@ -81,7 +82,7 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins, content_margins_(content_margins), footnote_margins_(content_margins_), title_icon_(new views::ImageView()), - default_title_(CreateDefaultTitleLabel(base::string16()).release()) { + default_title_(CreateDefaultTitleLabel(std::u16string()).release()) { AddChildView(title_icon_); default_title_->SetVisible(false); @@ -99,7 +100,7 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins, #if defined(OS_WIN) // Windows will automatically create a tooltip for the close button based on // the HTCLOSE result from NonClientHitTest(). - close->SetTooltipText(base::string16()); + close->SetTooltipText(std::u16string()); // Specify accessible name instead for screen readers. close->SetAccessibleName(l10n_util::GetStringUTF16(IDS_APP_CLOSE)); #endif @@ -114,7 +115,7 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins, this)); minimize->SetVisible(false); #if defined(OS_WIN) - minimize->SetTooltipText(base::string16()); + minimize->SetTooltipText(std::u16string()); minimize->SetAccessibleName( l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE)); #endif @@ -124,6 +125,7 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins, kProgressIndicatorHeight, /*allow_round_corner=*/false); progress_indicator->SetBackgroundColor(SK_ColorTRANSPARENT); progress_indicator->SetVisible(false); + progress_indicator->GetViewAccessibility().OverrideIsIgnored(true); progress_indicator_ = AddChildView(std::move(progress_indicator)); } @@ -131,7 +133,7 @@ BubbleFrameView::~BubbleFrameView() = default; // static std::unique_ptr